Merge redesign into main (#111)

This commit is contained in:
video-prize-ranch 2023-06-10 12:04:29 -04:00
parent 922480f05a
commit 4de1fa1e79
No known key found for this signature in database
52 changed files with 598 additions and 371 deletions

47
.air.toml Normal file
View File

@ -0,0 +1,47 @@
# Config file for [Air](https://github.com/cosmtrek/air) in TOML format
# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"
[build]
# Just plain old shell command. You could use `make` as well.
cmd = "ENV=dev go build -o ./tmp/rimgo ./main.go"
# Binary file yields from `cmd`.
bin = "./tmp/rimgo"
# Customize binary.
full_bin = "./tmp/rimgo"
# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html", "mustache", "hbs", "pug", "css"]
# Ignore these filename extensions or directories.
exclude_dir = ["tmp", "vendor", "node_modules"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms
[log]
# Show log time
time = false
[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# Delete tmp directory on exit
clean_on_exit = true

View File

@ -1,3 +1,3 @@
node_modules
samples
dist
.env
tmp
static/app.css

6
.gitignore vendored
View File

@ -1,3 +1,3 @@
dist
node_modules
.env
.env
tmp
static/app.css

View File

@ -3,6 +3,7 @@ package api
import (
"io"
"net/http"
"regexp"
"strings"
"sync"
"time"
@ -34,6 +35,8 @@ type Submission struct {
IsAlbum bool
}
var imgurRe = regexp.MustCompile(`https?://i?\.?imgur\.com`)
func (client *Client) FetchUser(username string) (User, error) {
cacheData, found := client.Cache.Get(username + "-user")
if found {
@ -108,10 +111,15 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
}
id := value.Get("id").String()
link := "/a/" + id
if value.Get("in_gallery").Bool() {
link = "/gallery/" + id
}
submissions = append(submissions, Submission{
Id: id,
Link: "/a/" + id,
Link: link,
Title: value.Get("title").String(),
Cover: cover,
Points: value.Get("points").Int(),

51
main.go
View File

@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"net/http"
"os"
"time"
"codeberg.org/video-prize-ranch/rimgo/pages"
@ -29,8 +30,12 @@ func main() {
pages.InitializeApiClient()
engine := handlebars.NewFileSystem(http.FS(views.GetFiles()), ".hbs")
views := http.FS(views.GetFiles())
if os.Getenv("ENV") == "dev" {
views = http.Dir("./views")
}
engine := handlebars.NewFileSystem(views, ".hbs")
engine.AddFunc("noteq", func(a interface{}, b interface{}, options *raymond.Options) interface{} {
if raymond.Str(a) != raymond.Str(b) {
return options.Fn()
@ -67,19 +72,34 @@ func main() {
fmt.Println(e)
},
}))
app.Use("/static", filesystem.New(filesystem.Config{
Next: func(c *fiber.Ctx) bool {
c.Response().Header.Add("Cache-Control", "public,max-age=2592000")
return false
},
Root: http.FS(static.GetFiles()),
}))
app.Use(cache.New(cache.Config{
Expiration: 30 * time.Minute,
MaxBytes: 25000000,
CacheControl: true,
StoreResponseHeaders: true,
}))
if os.Getenv("ENV") == "dev" {
app.Use("/static", filesystem.New(filesystem.Config{
MaxAge: 2592000,
Root: http.Dir("./static"),
}))
app.Get("/errors/429", func(c *fiber.Ctx) error {
return c.Render("errors/429", nil)
})
app.Get("/errors/404", func(c *fiber.Ctx) error {
return c.Render("errors/404", nil)
})
app.Get("/errors/error", func(c *fiber.Ctx) error {
return c.Render("errors/error", fiber.Map{
"err": "Test error",
})
})
} else {
app.Use("/static", filesystem.New(filesystem.Config{
Root: http.FS(static.GetFiles()),
}))
app.Use(cache.New(cache.Config{
Expiration: 30 * time.Minute,
MaxBytes: 25000000,
CacheControl: true,
StoreResponseHeaders: true,
}))
}
app.Get("/robots.txt", func(c *fiber.Ctx) error {
file, _ := static.GetFiles().ReadFile("robots.txt")
@ -93,6 +113,7 @@ func main() {
})
app.Get("/", pages.HandleFrontpage)
app.Get("/about", pages.HandleAbout)
app.Get("/privacy", pages.HandlePrivacy)
app.Get("/a/:postID", pages.HandlePost)
app.Get("/a/:postID/embed", pages.HandleEmbed)

22
pages/about.go Normal file
View File

@ -0,0 +1,22 @@
package pages
import (
"os"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleAbout(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("about", fiber.Map{
"proto": c.Protocol(),
"domain": c.Hostname(),
"force_webp": os.Getenv("FORCE_WEBP"),
})
}

View File

@ -1,12 +1,12 @@
package pages
import (
"os"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
var VersionInfo string
func HandleFrontpage(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
@ -14,8 +14,7 @@ func HandleFrontpage(c *fiber.Ctx) error {
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("frontpage", fiber.Map{
"proto": c.Protocol(),
"domain": c.Hostname(),
"force_webp": os.Getenv("FORCE_WEBP"),
"config": utils.Config,
"version": VersionInfo,
})
}

View File

@ -59,17 +59,21 @@ func handleMedia(c *fiber.Ctx, url string) error {
c.Status(res.StatusCode)
if res.StatusCode == 404 {
return c.Render("errors/404", nil)
return c.Render("errors/404", fiber.Map{
"path": c.Path(),
})
} else if res.StatusCode == 429 {
return c.Render("errors/429", nil)
return c.Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
c.Set("Accept-Ranges", "bytes")
c.Set("Content-Type", res.Header.Get("Content-Type"));
c.Set("Content-Length", res.Header.Get("Content-Length"))
if res.Header.Get("Content-Range") != "" {
c.Set("Content-Range", res.Header.Get("Content-Range"))
}
return c.SendStream(res.Body)
}

View File

@ -24,7 +24,9 @@ func HandlePost(c *fiber.Ctx) error {
post, err = ApiClient.FetchMedia(c.Params("postID"))
}
if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", nil)
return c.Status(429).Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
return c.Status(404).Render("errors/404", nil)

View File

@ -6,8 +6,6 @@ import (
"codeberg.org/video-prize-ranch/rimgo/utils"
)
var VersionInfo string
func HandlePrivacy(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")

View File

@ -30,7 +30,9 @@ func HandleTag(c *fiber.Ctx) error {
tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page)
if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", nil)
return c.Status(429).Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
if err != nil {
return err

View File

@ -25,7 +25,9 @@ func HandleUser(c *fiber.Ctx) error {
user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", nil)
return c.Status(429).Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
if err != nil {
return err
@ -37,7 +39,9 @@ func HandleUser(c *fiber.Ctx) error {
submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page)
if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429)
return c.Render("errors/429", nil)
return c.Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
if err != nil {
return err

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M231.39 132.94A8 8 0 0 0 224 128h-40V48a16 16 0 0 0-16-16H88a16 16 0 0 0-16 16v80H32a8 8 0 0 0-5.66 13.66l96 96a8 8 0 0 0 11.32 0l96-96a8 8 0 0 0 1.73-8.72ZM128 220.69L51.31 144H80a8 8 0 0 0 8-8V48h80v88a8 8 0 0 0 8 8h28.69Z"/></svg>

After

Width:  |  Height:  |  Size: 347 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="m229.66 114.34l-96-96a8 8 0 0 0-11.32 0l-96 96A8 8 0 0 0 32 128h40v80a16 16 0 0 0 16 16h80a16 16 0 0 0 16-16v-80h40a8 8 0 0 0 5.66-13.66ZM176 112a8 8 0 0 0-8 8v88H88v-88a8 8 0 0 0-8-8H51.31L128 35.31L204.69 112Z"/></svg>

After

Width:  |  Height:  |  Size: 334 B

1
static/icons/PhChat.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M216 48H40a16 16 0 0 0-16 16v160a15.84 15.84 0 0 0 9.25 14.5A16.05 16.05 0 0 0 40 240a15.89 15.89 0 0 0 10.25-3.78a.69.69 0 0 0 .13-.11L82.5 208H216a16 16 0 0 0 16-16V64a16 16 0 0 0-16-16ZM40 224Zm176-32H82.5a16 16 0 0 0-10.3 3.75l-.12.11L40 224V64h176Z"/></svg>

After

Width:  |  Height:  |  Size: 376 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M173.66 98.34a8 8 0 0 1 0 11.32l-56 56a8 8 0 0 1-11.32 0l-24-24a8 8 0 0 1 11.32-11.32L112 148.69l50.34-50.35a8 8 0 0 1 11.32 0ZM232 128A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104Zm-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88Z"/></svg>

After

Width:  |  Height:  |  Size: 355 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M224 72h-16v-8a24 24 0 0 0-24-24H40a24 24 0 0 0-24 24v96a24 24 0 0 0 24 24h112v8a24 24 0 0 0 24 24h48a24 24 0 0 0 24-24V96a24 24 0 0 0-24-24ZM40 168a8 8 0 0 1-8-8V64a8 8 0 0 1 8-8h144a8 8 0 0 1 8 8v8h-16a24 24 0 0 0-24 24v72Zm192 24a8 8 0 0 1-8 8h-48a8 8 0 0 1-8-8V96a8 8 0 0 1 8-8h48a8 8 0 0 1 8 8Zm-96 16a8 8 0 0 1-8 8H88a8 8 0 0 1 0-16h40a8 8 0 0 1 8 8Zm80-96a8 8 0 0 1-8 8h-16a8 8 0 0 1 0-16h16a8 8 0 0 1 8 8Z"/></svg>

After

Width:  |  Height:  |  Size: 536 B

1
static/icons/PhEye.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M247.31 124.76c-.35-.79-8.82-19.58-27.65-38.41C194.57 61.26 162.88 48 128 48S61.43 61.26 36.34 86.35C17.51 105.18 9 124 8.69 124.76a8 8 0 0 0 0 6.5c.35.79 8.82 19.57 27.65 38.4C61.43 194.74 93.12 208 128 208s66.57-13.26 91.66-38.34c18.83-18.83 27.3-37.61 27.65-38.4a8 8 0 0 0 0-6.5ZM128 192c-30.78 0-57.67-11.19-79.93-33.25A133.47 133.47 0 0 1 25 128a133.33 133.33 0 0 1 23.07-30.75C70.33 75.19 97.22 64 128 64s57.67 11.19 79.93 33.25A133.46 133.46 0 0 1 231.05 128c-7.21 13.46-38.62 64-103.05 64Zm0-112a48 48 0 1 0 48 48a48.05 48.05 0 0 0-48-48Zm0 80a32 32 0 1 1 32-32a32 32 0 0 1-32 32Z"/></svg>

After

Width:  |  Height:  |  Size: 711 B

1
static/icons/PhGlobe.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm-26.37 144h52.74C149 186.34 140 202.87 128 215.89c-12-13.02-21-29.55-26.37-47.89ZM98 152a145.72 145.72 0 0 1 0-48h60a145.72 145.72 0 0 1 0 48Zm-58-24a87.61 87.61 0 0 1 3.33-24h38.46a161.79 161.79 0 0 0 0 48H43.33A87.61 87.61 0 0 1 40 128Zm114.37-40h-52.74C107 69.66 116 53.13 128 40.11c12 13.02 21 29.55 26.37 47.89Zm19.84 16h38.46a88.15 88.15 0 0 1 0 48h-38.46a161.79 161.79 0 0 0 0-48Zm32.16-16h-35.43a142.39 142.39 0 0 0-20.26-45a88.37 88.37 0 0 1 55.69 45ZM105.32 43a142.39 142.39 0 0 0-20.26 45H49.63a88.37 88.37 0 0 1 55.69-45ZM49.63 168h35.43a142.39 142.39 0 0 0 20.26 45a88.37 88.37 0 0 1-55.69-45Zm101.05 45a142.39 142.39 0 0 0 20.26-45h35.43a88.37 88.37 0 0 1-55.69 45Z"/></svg>

After

Width:  |  Height:  |  Size: 860 B

1
static/icons/PhLink.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M137.54 186.36a8 8 0 0 1 0 11.31l-9.94 10a56 56 0 0 1-79.22-79.27l24.12-24.12a56 56 0 0 1 76.81-2.28a8 8 0 1 1-10.64 12a40 40 0 0 0-54.85 1.63L59.7 139.72a40 40 0 0 0 56.58 56.58l9.94-9.94a8 8 0 0 1 11.32 0Zm70.08-138a56.08 56.08 0 0 0-79.22 0l-9.94 9.95a8 8 0 0 0 11.32 11.31l9.94-9.94a40 40 0 0 1 56.58 56.58l-24.12 24.14a40 40 0 0 1-54.85 1.6a8 8 0 1 0-10.64 12a56 56 0 0 0 76.81-2.26l24.12-24.12a56.08 56.08 0 0 0 0-79.24Z"/></svg>

After

Width:  |  Height:  |  Size: 549 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72Zm-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72ZM120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0Zm20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12Z"/></svg>

After

Width:  |  Height:  |  Size: 555 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm0 192a88 88 0 1 1 88-88a88.1 88.1 0 0 1-88 88Zm-8-80V80a8 8 0 0 1 16 0v56a8 8 0 0 1-16 0Zm20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12Z"/></svg>

After

Width:  |  Height:  |  Size: 313 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M226.76 69a8 8 0 0 0-12.84-2.88l-40.3 37.19l-17.23-3.7l-3.7-17.23l37.19-40.3A8 8 0 0 0 187 29.24A72 72 0 0 0 88 96a72.34 72.34 0 0 0 6 28.94L33.79 177c-.15.12-.29.26-.43.39a32 32 0 0 0 45.26 45.26c.13-.13.27-.28.39-.42L131.06 162A72 72 0 0 0 232 96a71.56 71.56 0 0 0-5.24-27ZM160 152a56.14 56.14 0 0 1-27.07-7a8 8 0 0 0-9.92 1.77l-55.9 64.74a16 16 0 0 1-22.62-22.62L109.18 133a8 8 0 0 0 1.77-9.93a56 56 0 0 1 58.36-82.31l-31.2 33.81a8 8 0 0 0-1.94 7.1l5.66 26.33a8 8 0 0 0 6.14 6.14l26.35 5.66a8 8 0 0 0 7.1-1.94l33.81-31.2A56.06 56.06 0 0 1 160 152Z"/></svg>

After

Width:  |  Height:  |  Size: 673 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2b95f2" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>

Before

Width:  |  Height:  |  Size: 351 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2b95f2" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-triangle"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>

Before

Width:  |  Height:  |  Size: 419 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2b95f2" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check-circle"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>

Before

Width:  |  Height:  |  Size: 323 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>

Before

Width:  |  Height:  |  Size: 269 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>

Before

Width:  |  Height:  |  Size: 268 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>

Before

Width:  |  Height:  |  Size: 316 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-hash"><line x1="4" y1="9" x2="20" y2="9"></line><line x1="4" y1="15" x2="20" y2="15"></line><line x1="10" y1="3" x2="8" y2="21"></line><line x1="16" y1="3" x2="14" y2="21"></line></svg>

Before

Width:  |  Height:  |  Size: 389 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>

Before

Width:  |  Height:  |  Size: 371 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-square"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>

Before

Width:  |  Height:  |  Size: 305 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-smartphone"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect><line x1="12" y1="18" x2="12.01" y2="18"></line></svg>

Before

Width:  |  Height:  |  Size: 332 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-tool"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path></svg>

Before

Width:  |  Height:  |  Size: 386 B

74
static/tailwind.css Normal file
View File

@ -0,0 +1,74 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0 24vw;
}
p a {
text-decoration: underline
}
.posts {
margin-top: 1em;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-auto-rows: 1fr;
gap: 1rem;
}
.posts img:not(.icon),
.posts video:not(:fullscreen) {
object-fit: cover;
aspect-ratio: 1;
}
#comments__expandBtn {
display: none;
}
.comments__expandBtn__label {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
cursor: pointer;
user-select: none;
text-decoration: none;
color: #fff
}
.comments__expandBtn__icon {
font-size: 24px;
}
#comments__expandBtn ~ .comments__expandBtn__label > span::after {
content: "⌄";
}
#comments__expandBtn:checked ~ .comments__expandBtn__label > span::after {
content: "⌃";
}
#comments__expandBtn:checked ~ .comments {
display: none;
}
.comment__media {
height: 12em;
display: block;
margin: 0.5em 0;
}
@media only screen and (max-width: 1280px) {
body {
margin: 0 8vw;
}
}
@media only screen and (max-width: 812px) {
body {
margin: 0 4vw;
}
}

8
tailwind.config.js Normal file
View File

@ -0,0 +1,8 @@
module.exports = {
content: ["./views/*.hbs", "./views/**/*.hbs"],
theme: {
extend: {},
},
variants: {},
plugins: [],
};

105
views/about.hbs Normal file
View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>About - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main class="my-8">
<p>An alternative frontend for Imgur. Originally based on <a href="https://codeberg.org/3np/rimgu" rel="noreferrer">rimgu</a>.</p>
<h2 class="font-bold text-2xl my-2">Features</h2>
<ul class="list-disc ml-4">
<li>Lightweight</li>
<li>No JavaScript</li>
<li>No ads or tracking</li>
<li>No sign up or app install prompts</li>
<li>Bandwidth efficient - automatically uses newer image formats (if enabled)</li>
</ul>
<h2 class="font-bold text-2xl my-2">Comparison</h2>
<p>Comparing rimgo to Imgur.</p>
<h3 class="font-bold text-xl my-2">Speed</h3>
<p>Tested using <a href="https://pagespeed.web.dev/" rel="nofollow noreferrer">Google PageSpeed Insights</a>.</p>
<table>
<tr>
<td></td>
<td><a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fi.bcow.xyz%2Fgallery%2FgYiQLWy" rel="nofollow noreferrer">rimgo</a></td>
<td><a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fimgur.com%2Fgallery%2FgYiQLWy" rel="nofollow noreferrer">Imgur</a></td>
</tr>
<tr>
<td>Performance</td>
<td>91</td>
<td>28</td>
</tr>
<tr>
<td>Request count</td>
<td>29</td>
<td>340</td>
</tr>
<tr>
<td>Resource Size</td>
<td>218 KiB</td>
<td>2,542 KiB</td>
</tr>
<tr>
<td>Time to Interactive</td>
<td>1.6s</td>
<td>23.8s</td>
</tr>
</table>
<h3 class="font-bold text-xl my-2">Privacy</h3>
<p>Imgur collects information about your device and uses tracking cookies for advertising, this is mentioned in their <a href="https://imgur.com/privacy/" rel="nofollow noreferrer">privacy policy</a>. <a href="https://themarkup.org/blacklight" rel="nofollow noreferrer">Blacklight</a> found 31 trackers and 87 third-party cookies.</p>
<p>See what cookies and trackers Imgur uses and where your data gets sent: <a href="https://themarkup.org/blacklight?url=imgur.com" rel="nofollow noreferrer">https://themarkup.org/blacklight?url=imgur.com</a></p>
<h2 class="font-bold text-2xl my-2">Usage</h2>
<p>Just replace imgur.com or i.imgur.com with <code>{{domain}}</code> (add stack/ before the media ID for i.stack.imgur.com). You can setup automatic redirects using <a href="https://github.com/libredirect/libredirect" rel="nofollow noreferrer">LibRedirect</a> (recommended) or <a href="https://github.com/einaregilsson/Redirector" rel="nofollow noreferrer">Redirector</a>.</p>
{{#if force_webp}}
<p>To download images as their original filetype, add <code>?no_webp=1</code> to the end of the image URL.</p>
{{/if}}
<h2 class="font-bold text-2xl my-2">Automatically redirect links</h2>
<h3 class="font-bold text-xl my-2">LibRedirect</h3>
<p>Use <a href="https://github.com/libredirect/libredirect" rel="nofollow noreferrer">LibRedirect</a> to automatically redirect Imgur links to rimgo!</p>
<h3 class="font-bold text-xl my-2">GreaseMonkey script</h3>
<p>There is a script to redirect Imgur links to rimgo. <a rel="noreferrer" href="https://codeberg.org/zortazert/GreaseMonkey-Redirect/src/branch/main/imgur-to-rimgo.user.js">https://codeberg.org/zortazert/GreaseMonkey-Redirect/src/branch/main/imgur-to-rimgo.user.js</a></p>
<h3 class="font-bold text-xl my-2">Redirector</h3>
<p>You can use the <a href="https://github.com/einaregilsson/Redirector" rel="nofollow noreferrer">Redirector</a> extension to redirect Imgur links to rimgo with the configuration below:</p>
<ul class="list-disc ml-4">
<li>Description: Imgur -> rimgo</li>
<li>Example URL: https://imgur.com/a/H8M4rcp</li>
<li>Include pattern: <code>^https?://i?.?imgur.com(/.*)?$</code></li>
<li>Redirect to: <code>{{proto}}://{{domain}}$1</code></li>
<li>Pattern type: Regular Expression</li>
<li>Advanced Options > Apply to: Check Images</li>
</ul>
<br/>
<p>For Stack Overflow Images:</p>
<ul class="list-disc ml-4">
<li>Description: Stack Overflow Imgur -> rimgo</li>
<li>Example URL: https://i.stack.imgur.com/BTKqD.png?s=128&g=1</li>
<li>Include pattern: <code>^https?://i\.stack\.imgur\.com(/.*)?$</code></li>
<li>Redirect to: <code>{{proto}}://{{domain}}/stack$1</code></li>
<li>Pattern type: Regular Expression</li>
<li>Advanced Options > Apply to: Check Images</li>
</ul>
<h2 class="font-bold text-2xl my-2">Notice</h2>
<p>All images and media are from Imgur. rimgo does not allow uploads or comments. Any issues with content should be reported to Imgur.</p>
</main>
{{> partials/footer }}
</body>
</html>

View File

@ -2,21 +2,20 @@
<html lang="en">
<head>
{{> 'partials/head' }}
<title>Not Found - rimgo</title>
<link rel="stylesheet" href="/static/css/error.css" />
<title>404 Not Found - rimgo</title>
{{> partials/head }}
</head>
<body>
{{> 'partials/header' }}
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main>
<h2 class="errorTitle">404 Not Found</h2>
<p class="errorTitle">Click <a href="/">here</a> to return to home.</p>
<h2 class="text-2xl font-bold">Not Found</h2>
<p>Click <a href="/">here</a> to return to home.</p>
</main>
{{> partials/footer }}
</body>
</html>

View File

@ -2,21 +2,20 @@
<html lang="en">
<head>
{{> 'partials/head' }}
<link rel="stylesheet" href="/static/css/error.css" />
<title>Rate limited by Imgur - rimgo</title>
{{> partials/head }}
</head>
<body>
{{> 'partials/header' }}
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main>
<h2 class="errorTitle">Rate limited by Imgur</h2>
<p class="errorTitle">This instance has been temporarily blocked by Imgur. <a href="https://rimgo.codeberg.page/">Try using another instance</a>.</p>
<h2 class="text-2xl font-bold">Rate limited by Imgur</h2>
<p>This instance has been temporarily blocked by Imgur. <a href="https://rimgo.codeberg.page/#{{ path }}">Try using another instance ></a></p>
</main>
{{> partials/footer }}
</body>
</html>

View File

@ -2,22 +2,21 @@
<html lang="en">
<head>
{{> 'partials/head' }}
<link rel="stylesheet" href="/static/css/error.css" />
<title>Error - rimgo</title>
{{> partials/head }}
</head>
<body>
{{> 'partials/header' }}
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main>
<h2 class="errorTitle">An error occurred</h2>
<main class="flex flex-col">
<h2 class="text-2xl font-bold">An error occurred</h2>
<p>You may have found a bug in rimgo. If this is a bug, open an issue on <a href="https://codeberg.org/video-prize-ranch/rimgo/issues/new">Codeberg</a>.</p>
<code>{{err}}</code>
<code class="mt-4 p-2 bg-slate-600 rounded-md">{{err}}</code>
</main>
{{> partials/footer }}
</body>
</html>

View File

@ -5,104 +5,49 @@
<title>rimgo</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/frontpage.css" />
</head>
<body>
{{> partials/header }}
<main>
<p>An alternative frontend for Imgur. Originally based on <a href="https://codeberg.org/3np/rimgu" rel="noreferrer">rimgu</a>.</p>
<h2>Features</h2>
<ul>
<li>Lightweight</li>
<li>No JavaScript</li>
<li>No ads or tracking</li>
<li>No sign up or app install prompts</li>
<li>Bandwidth efficient - automatically uses newer image formats (if enabled)</li>
</ul>
<h2>Comparison</h2>
<p>Comparing rimgo to Imgur.</p>
<h3>Speed</h3>
<p>Tested using <a href="https://pagespeed.web.dev/" rel="nofollow noreferrer">Google PageSpeed Insights</a>.</p>
<table>
<tr>
<td></td>
<td><a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fi.bcow.xyz%2Fgallery%2FgYiQLWy" rel="nofollow noreferrer">rimgo</a></td>
<td><a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fimgur.com%2Fgallery%2FgYiQLWy" rel="nofollow noreferrer">Imgur</a></td>
</tr>
<tr>
<td>Performance</td>
<td>91</td>
<td>28</td>
</tr>
<tr>
<td>Request count</td>
<td>29</td>
<td>340</td>
</tr>
<tr>
<td>Resource Size</td>
<td>218 KiB</td>
<td>2,542 KiB</td>
</tr>
<tr>
<td>Time to Interactive</td>
<td>1.6s</td>
<td>23.8s</td>
</tr>
</table>
<h3>Privacy</h3>
<p>Imgur collects information about your device and uses tracking cookies for advertising, this is mentioned in their <a href="https://imgur.com/privacy/" rel="nofollow noreferrer">privacy policy</a>. <a href="https://themarkup.org/blacklight" rel="nofollow noreferrer">Blacklight</a> found 31 trackers and 87 third-party cookies.</p>
<p>See what cookies and trackers Imgur uses and where your data gets sent: <a href="https://themarkup.org/blacklight?url=imgur.com" rel="nofollow noreferrer">https://themarkup.org/blacklight?url=imgur.com</a></p>
<h2>Usage</h2>
<p>Just replace imgur.com or i.imgur.com with <code>{{domain}}</code> (add stack/ before the media ID for i.stack.imgur.com). You can setup automatic redirects using <a href="https://github.com/libredirect/libredirect" rel="nofollow noreferrer">LibRedirect</a> (recommended) or <a href="https://github.com/einaregilsson/Redirector" rel="nofollow noreferrer">Redirector</a>.</p>
{{#if force_webp}}
<p>To download images as their original filetype, add <code>?no_webp=1</code> to the end of the image URL.</p>
{{/if}}
<h2>Automatically redirect links</h2>
<h3>LibRedirect</h3>
<p>Use <a href="https://github.com/libredirect/libredirect" rel="nofollow noreferrer">LibRedirect</a> to automatically redirect Imgur links to rimgo!</p>
<h3>GreaseMonkey script</h3>
<p>There is a script to redirect Imgur links to rimgo. <a rel="noreferrer" href="https://codeberg.org/zortazert/GreaseMonkey-Redirect/src/branch/main/imgur-to-rimgo.user.js">https://codeberg.org/zortazert/GreaseMonkey-Redirect/src/branch/main/imgur-to-rimgo.user.js</a></p>
<h3>Redirector</h3>
<p>You can use the <a href="https://github.com/einaregilsson/Redirector" rel="nofollow noreferrer">Redirector</a> extension to redirect Imgur links to rimgo with the configuration below:</p>
<ul>
<li>Description: Imgur -> rimgo</li>
<li>Example URL: https://imgur.com/a/H8M4rcp</li>
<li>Include pattern: <code>^https?://i?.?imgur.com(/.*)?$</code></li>
<li>Redirect to: <code>{{proto}}://{{domain}}$1</code></li>
<li>Pattern type: Regular Expression</li>
<li>Advanced Options > Apply to: Check Images</li>
</ul>
<p>For Stack Overflow Images:</p>
<ul>
<li>Description: Stack Overflow Imgur -> rimgo</li>
<li>Example URL: https://i.stack.imgur.com/BTKqD.png?s=128&g=1</li>
<li>Include pattern: <code>^https?://i\.stack\.imgur\.com(/.*)?$</code></li>
<li>Redirect to: <code>{{proto}}://{{domain}}/stack$1</code></li>
<li>Pattern type: Regular Expression</li>
<li>Advanced Options > Apply to: Check Images</li>
</ul>
<h2>Notice</h2>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<header class="my-8 p-8 rounded-xl flex flex-col gap-4 items-center justify-center bg-gradient-to-r from-blue-400 to-emerald-400">
<h2 class="font-bold text-white text-2xl">The fast, private image viewer for Imgur.</h2>
<!--<input class="p-2 rounded-lg bg-slate-200 text-black w-full lg:w-1/2" type="text" placeholder="Search or paste a link">-->
</header>
<main class="my-8">
<h2 class="font-bold text-2xl">What is rimgo?</h2>
<p>
rimgo is an alternative frontend for Imgur.
Originally based on <a href="https://codeberg.org/3np/rimgu" rel="noreferrer">rimgu</a>.
It's a way to access Imgur without the ads, tracking, and other garbage.
rimgo is not affiliated with Imgur, all content is proxied from Imgur.
</p>
<br/>
<h3 class="font-bold text-xl">Notice</h3>
<p>All images and media are from Imgur. rimgo does not allow uploads or comments. Any issues with content should be reported to Imgur.</p>
</main>
<h2 class="font-bold text-2xl">This instance</h2>
<section class="my-4 lg:m-4 flex flex-col lg:flex-row gap-4 items-center">
{{> partials/privacy }}
<div class="self-start">
<h2 class="text-xl my-2 font-bold">Additional information</h2>
<ul>
<li>Version: {{version}}</li>
<li>Country: {{config.Privacy.country}}</li>
<li>Provider: {{config.Privacy.provider}}</li>
{{#if config.Privacy.cloudflare}}
<li>Using Cloudflare?: Yes</li>
{{else}}
<li>Using Cloudflare?: No</li>
{{/if}}
</ul>
</div>
</section>
<p><a href="/privacy">Learn more about instance privacy ></a></p>
{{> partials/footer }}
</body>
</html>
</html>

View File

@ -1,30 +1,32 @@
<div class="comment flex flex-col">
<div class="comment__user">
<div class="flex flex-col gap-2">
<div class="flex gap-2 items-center">
{{#noteq this.User.Username "[deleted]"}}
<img src="{{this.User.Avatar}}" class="pfp" width="24" height="24" loading="lazy">
<img src="{{this.User.Avatar}}" class="rounded-full" width="24" height="24" loading="lazy">
<a href="/user/{{this.User.Username}}">
<p class="comment__user__username"><b>{{this.User.Username}}</b></p>
<p class="whitespace-nowrap text-ellipsis overflow-hidden"><b>{{this.User.Username}}</b></p>
</a>
{{/noteq}}
{{#equal this.User.Username "[deleted]"}}
<p class="comment__user__username"><b>[deleted]</b></p>
<p class="whitespace-nowrap text-ellipsis overflow-hidden"><b>[deleted]</b></p>
{{/equal}}
</div>
<div>
<p>{{{this.Comment}}}</p>
<div>
<div class="flex gap-2">
<span title="{{this.CreatedAt}}">{{this.RelTime}}</span>
{{#if this.DeletedAt}}
<span class="comment__updatedDate">(deleted {{this.DeletedAt}})</span>
<span class="text-md">(deleted {{this.DeletedAt}})</span>
{{/if}}
|
<img class="icon" src="/static/icons/chevron-up.svg" alt="Likes"> {{this.Upvotes}}
<img class="icon" src="/static/icons/chevron-down.svg" alt="Dislikes"> {{this.Downvotes}}
<img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Likes" width="24px" height="24px"> {{this.Upvotes}}
<img class="invert icon" src="/static/icons/PhArrowFatDown.svg" alt="Dislikes" width="24px" height="24px"> {{this.Downvotes}}
</div>
</div>
<div class="replies">
{{#if this.Comments}}
<div class="ml-4 p-2 border-solid border-l-2 border-slate-400">
{{#each this.Comments}}
{{> partials/comment }}
{{/each}}
</div>
{{/if}}
</div>

View File

@ -1,4 +1,14 @@
<footer class="flex flex-center">
<a href="/privacy">Privacy</a>
<a href="https://codeberg.org/video-prize-ranch/rimgo" rel="noreferrer">Source Code</a>
<footer class="mt-24 mb-12">
<div class="mb-1 flex gap-4 font-bold">
<a href="/">
<div class="flex">
<img src="/static/img/rimgo.svg" class="invert hue-rotate-180" width="32" height="32" />
<h1 class="text-md font-extrabold">rimgo</h1>
</div>
</a>
<a href="https://codeberg.org/rimgo/rimgo">Source Code</a>
<a href="/about">About</a>
<a href="/privacy">Privacy</a>
</div>
<p class="text-md text-slate-200">rimgo does not allow uploads or host any content. Issues with content should be reported to Imgur.</p>
</footer>

View File

@ -12,5 +12,4 @@
<meta name="msapplication-config" content="/static/favicon/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="/static/css/normalize.css"/>
<link rel="stylesheet" href="/static/css/base.css"/>
<link rel="stylesheet" href="/static/app.css" />

View File

@ -1,8 +0,0 @@
<nav class="flex flex-center">
<a href="/">
<img src="/static/img/rimgo.svg" width="64" height="64" class="logo" alt="Logo">
</a>
<a href="/">
<h2>rimgo</h2>
</a>
</nav>

6
views/partials/nav.hbs Normal file
View File

@ -0,0 +1,6 @@
<a href="/">
<nav class="m-4 flex items-center justify-center">
<img src="/static/img/rimgo.svg" class="invert hue-rotate-180" width="72" height="72" />
<h1 class="font-extrabold text-3xl">rimgo</h1>
</nav>
</a>

View File

@ -1,5 +1,5 @@
<a href="{{Link}}">
<div class="post">
<div class="bg-slate-600 rounded-lg">
{{#equal Cover.Type "video"}}
<video controls loop poster="/{{Cover.Id}}.webp" preload="none" width="100%" height="100%">
<source src="{{Cover.Url}}" type="video/mp4" />
@ -8,18 +8,18 @@
{{#equal Cover.Type "image"}}
<img src="{{Cover.Url}}" loading="lazy" width="100%" height="100%">
{{/equal}}
<p class="post__title">{{Title}}</p>
<p class="m-2 text-ellipsis whitespace-nowrap overflow-hidden">{{Title}}</p>
<div class="flex gap-2 p-2">
<div>
<img class="icon" src="/static/icons/chevron-up.svg" alt="Points">
<div class="flex gap-1">
<img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Points" width="18px" height="18px">
{{Points}}
</div>
<div>
<img class="icon" src="/static/icons/message-square.svg" alt="Comments">
<div class="flex gap-1">
<img class="invert icon" src="/static/icons/PhChat.svg" alt="Comments" width="18px" height="18px">
{{Comments}}
</div>
<div>
<img class="icon" src="/static/icons/eye.svg" alt="Views">
<div class="flex gap-1">
<img class="invert icon" src="/static/icons/PhEye.svg" alt="Views" width="18px" height="18px">
{{Views}}
</div>
</div>

View File

@ -0,0 +1,48 @@
{{#if config.Privacy.not_collected}}
<div class="flex flex-col items-center w-full lg:w-1/2 p-4 bg-slate-600 rounded-lg">
<img class="invert" src="/static/icons/PhCheckCircle.svg" alt="" height="36" width="36" />
<h2 class="font-bold text-xl">Data not collected</h2>
<p class="text-lg">This instance does not collect any data.</p>
</div>
{{/if}}
{{#unless config.Privacy.set}}
<div class="flex flex-col items-center w-full lg:w-1/2 p-4 bg-slate-600 rounded-lg">
<img class="invert" src="/static/icons/PhWarning.svg" alt="" height="36" width="36" />
<h2 class="font-bold text-xl">No details provided</h2>
<p class="text-lg">The operator of this instance will be required to provide privacy details to be added to the instance list.</p>
</div>
{{else}}
{{#unless config.Privacy.not_collected}}
<div class="flex flex-col items-center w-full lg:w-1/2 p-4 bg-slate-600 rounded-lg">
<img class="invert" src="/static/icons/PhWarningCircle.svg" alt="" height="36" width="36" />
<h2 class="font-bold text-xl">Data collected</h2>
<p class="text-lg">The following data may be collected:</p>
<ul class="flex flex-col">
{{#if config.Privacy.ip}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhGlobe.svg" alt="" width="24px" height="24px" />
Internet address (IP Address)
</li>
{{/if}}
{{#if config.Privacy.url}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhLink.svg" alt="" width="24px" height="24px" />
Page viewed (Request URL)
</li>
{{/if}}
{{#if config.Privacy.device}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhDevices.svg" alt="" width="24px" height="24px" />
Device Type (User agent)
</li>
{{/if}}
{{#if config.Privacy.diagnostics}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhWrench.svg" alt="" width="24px" height="24px" />
Diagnostics
</li>
{{/if}}
</ul>
</div>
{{/unless}}
{{/unless}}

View File

@ -7,62 +7,58 @@
{{post.Title}} -
{{/if}}
rimgo
</title>
</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/album.css" />
<link rel="stylesheet" href="/static/css/comments.css" />
</head>
<body>
{{> partials/header }}
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<header>
<h1>{{post.Title}}</h1>
<h1 class="text-3xl font-bold">{{post.Title}}</h1>
<p>{{post.CreatedAt}}</p>
</header>
<main>
<div class="flex flex-center-y gap-4">
<div class="flex gap-4 items-center my-4">
{{#if post.User.Username}}
<a href="/user/{{post.User.Username}}" class="user">
<img src="{{post.User.Avatar}}" class="pfp" width="36" height="36" />
<a href="/user/{{post.User.Username}}" class="flex gap-2 items-center">
<img src="{{post.User.Avatar}}" class="rounded-full" width="36" height="36" />
<p>
<b>{{post.User.Username}}</b>
</p>
</a>
{{/if}}
<div class="flex flex-center-y gap-2">
<div class="flex gap-2 items-center">
<div class="flex flex-center gap-2">
<img class="icon" src="/static/icons/eye.svg" alt="Views">
<img class="icon invert" src="/static/icons/PhEye.svg" alt="Views" width="24px" height="24px">
<p>{{post.Views}}</p>
</div>
{{#if post.SharedWithCommunity}}
<div class="flex flex-center gap-2">
<img class="icon" src="/static/icons/chevron-up.svg" alt="Likes">
<img class="icon invert" src="/static/icons/PhArrowFatUp.svg" alt="Likes" width="24px" height="24px">
<p>{{post.Upvotes}}</p>
</div>
<div class="flex flex-center gap-2">
<img class="icon" src="/static/icons/chevron-down.svg" alt="Dislikes">
<img class="icon invert" src="/static/icons/PhArrowFatDown.svg" alt="Dislikes" width="24px" height="24px">
<p>{{post.Downvotes}}</p>
</div>
{{/if}}
</div>
</div>
<div class="post__media flex flex-center flex-col">
<div class="flex flex-center flex-col">
{{#each post.Media}}
{{#if this.Title}}
<h4>{{this.Title}}</h4>
<h4 class="font-bold">{{this.Title}}</h4>
{{/if}}
{{#equal this.Type "image"}}
<img src="{{this.Url}}" loading="lazy">
<img class="my-2 max-h-96 object-contain" src="{{this.Url}}" loading="lazy">
{{/equal}}
{{#equal this.Type "video"}}
<video controls loop>
<video class="my-2 max-h-96 object-contain" controls loop>
<source type="{{this.MimeType}}" src="{{this.Url}}" />
</video>
{{/equal}}
@ -74,7 +70,7 @@
</div>
{{#if post.tags}}
<div class="tags">
<div class="flex gap-2 my-2 flex-flow-wrap">
<style nonce="{{nonce}}">
{{#each post.tags}}
.{{this.BackgroundId}} { background-image: url('{{this.Background}}') }
@ -82,8 +78,8 @@
</style>
{{#each post.tags}}
<a href="/t/{{this.Tag}}">
<div class="tag {{this.BackgroundId}}">
<p class="tag__display">{{this.Display}}</p>
<div class="rounded-md p-4 min-w-[110px] bg-slate-500 {{this.BackgroundId}}">
<p class="font-bold text-white text-center">{{this.Display}}</p>
</div>
</a>
{{/each}}
@ -94,13 +90,12 @@
<section>
{{#if comments}}
<div>
<hr>
<input id="comments__expandBtn" type="checkbox">
<label class="comments__expandBtn__label" for="comments__expandBtn">
<h3>Comments ({{post.Comments}})</h3>
<span class="comments__expandBtn__icon"></span>
<input id="comments__expandBtn" type="checkbox" checked>
<label class="comments__expandBtn__label my-2 py-4 border-solid border-t-2 border-slate-400" for="comments__expandBtn">
<h3 class="text-xl font-bold">Comments ({{post.Comments}})</h3>
<span class="text-xl font-bold"></span>
</label>
<div class="comments flex flex-col">
<div class="comments flex flex-col gap-2">
{{#each comments}}
{{> partials/comment }}
{{/each}}

View File

@ -2,18 +2,16 @@
<html lang="en">
<head>
{{> 'partials/head' }}
<title>Privacy - rimgo</title>
<link rel="stylesheet" href="/static/css/privacy.css">
<title>Instance privacy - rimgo</title>
{{> partials/head }}
</head>
<body>
{{> 'partials/header' }}
<main>
<h1>Instance Privacy</h1>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<header>
<h1 class="text-3xl font-bold">Instance Privacy</h1>
{{#if config.Privacy.policy}}
<p>The instance operator has indicated their instance's privacy practices below. For more information, see the
instance operator's <a href="{{config.Privacy.policy}}">privacy policy</a>.</p>
@ -22,95 +20,42 @@
{{/if}}
{{#if config.Privacy.message}}
<p>{{{config.Privacy.message}}}</p>
<p class="my-4">{{{config.Privacy.message}}}</p>
{{/if}}
{{#if config.Privacy.not_collected}}
<div class="badge">
<div class="flex flex-col flex-center p-2 gap-2">
<img class="icon largeIcon" src="/static/icons/check-circle.svg" alt="">
<h2>Data Not Collected</h2>
<p>The instance operator does not collect any data from this instance.</p>
</div>
</div>
{{/if}}
{{#unless config.Privacy.set}}
<div class="badge">
<div class="flex flex-col flex-center p-2 gap-2">
<img class="icon largeIcon" src="/static/icons/alert-triangle.svg" alt="">
<h3>No Details Provided</h3>
<p>The operator of this instance will be required to provide privacy details to be added to the instance list.
</p>
</div>
</div>
{{else}}
{{#unless config.Privacy.not_collected}}
<div class="badge">
<div class="flex flex-col flex-center p-2 gap-2">
<img class="icon largeIcon" src="/static/icons/alert-circle.svg" alt="">
<h2>Data Collected</h2>
<p>The following data may be collected:</p>
<ul>
{{#if config.Privacy.ip}}
<li>
<img class="icon" src="/static/icons/hash.svg" alt="">
Internet address (IP Address)
</li>
{{/if}}
{{#if config.Privacy.url}}
<li>
<img class="icon" src="/static/icons/link.svg" alt="">
Page viewed (Request URL)
</li>
{{/if}}
{{#if config.Privacy.device}}
<li>
<img class="icon" src="/static/icons/smartphone.svg" alt="">
Device Type (User agent)
</li>
{{/if}}
{{#if config.Privacy.diagnostics}}
<li>
<img class="icon" src="/static/icons/tool.svg" alt="">
Diagnostics
</li>
{{/if}}
</ul>
</div>
</div>
{{/unless}}
{{/unless}}
<details class="privacyDetails">
<summary>What's this?</summary>
<p>
Instance privacy aims to bring transparency to the data collected by frontends and encourage privacy friendly practices. There is often no privacy policy and users are forced to trust that the instance operator is not collecting data. However, there is a possibility that the instance operator can put false information so we encourage looking at other factors when selecting an instance.
</p>
<ul>
<li>
<img class="icon" src="/static/icons/hash.svg" alt="">
Internet address (IP Address) - This is an address that is given to your computer or internet connection.
This can be used to find your city or region and internet provider but can change depending on your connection.
</li>
<li>
<img class="icon" src="/static/icons/link.svg" alt="">
Page viewed (Request URL) - This is what page you are viewing. Searches are kept private.
</li>
<li>
<img class="icon" src="/static/icons/smartphone.svg" alt="">
Device Type (User agent) - This is what browser, device, and operating system you are using.
Advanced users can change this with an extension or browser setting.
</li>
<li>
<img class="icon" src="/static/icons/tool.svg" alt="">
Diagnostics - When this data is only collected when there is an error or only a short amount of time while
diagnosing an issue.
</li>
</ul>
</details>
<h2 class="addInfo">Additional information</h2>
</header>
<main class="flex justify-center w-full">
{{> partials/privacy }}
</main>
<section>
<h2 class="text-2xl my-4 font-bold">What is instance privacy?</h2>
<p>Instance privacy aims to bring transparency to the data collected by frontends and encourage privacy friendly practices. There is often no privacy policy and users are forced to trust that the instance operator is not collecting data. However, there is a possibility that the instance operator can put false information so we encourage looking at other factors when selecting an instance.</p>
<ul class="flex flex-col list-outside list-disc mt-2 ml-4">
<li>
<img class="inline invert" src="/static/icons/PhGlobe.svg" alt="" width="24px" height="24px" />
Internet address (IP Address) - This is an address that is given to your computer or internet connection.
This can be used to find your city or region and internet provider but can change depending on your connection.
</li>
<li>
<img class="inline invert" src="/static/icons/PhLink.svg" alt="" width="24px" height="24px" />
Page viewed (Request URL) - This is what page you are viewing.
</li>
<li>
<img class="inline invert" src="/static/icons/PhDevices.svg" alt="" width="24px" height="24px" />
Device Type (User agent) - This is what browser, device, and operating system you are using.
Advanced users can change this with an extension or browser setting.
</li>
<li>
<img class="inline invert" src="/static/icons/PhWrench.svg" alt="" width="24px" height="24px" />
Diagnostics - When this data is only collected when there is an error or only a short amount of time while
diagnosing an issue.
</li>
</ul>
</section>
<section>
<h2 class="text-2xl my-4 font-bold">Additional information</h2>
<ul>
<li>Version: {{version}}</li>
<li>Country: {{config.Privacy.country}}</li>
@ -121,7 +66,7 @@
<li>Using Cloudflare?: No</li>
{{/if}}
</ul>
</main>
</section>
{{> 'partials/footer' }}
</body>

View File

@ -5,46 +5,43 @@
<title>{{tag.Display}} - rimgo</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/base.css" />
<link rel="stylesheet" href="/static/css/tag.css" />
</head>
<body>
{{> partials/header }}
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main>
<div class="tagMeta" style="background-image: url('{{tag.Background}}');">
<div class="flex flex-center flex-col text-center">
<h2>{{tag.Display}}</h2>
<p>{{tag.PostCount}} posts</p>
</div>
<div class="flex flex-col gap-2">
{{#equal tag.Sort "popular"}}
<a href="?sort=popular"><b>Popular</b></a>
<a href="?sort=newest">Newest</a>
<a href="?sort=best">Best</a>
{{/equal}}
{{#equal tag.Sort "newest"}}
<a href="?sort=popular">Popular</a>
<a href="?sort=newest"><b>Newest</b></a>
<a href="?sort=best">Best</a>
{{/equal}}
{{#equal tag.Sort "best"}}
<a href="?sort=popular">Popular</a>
<a href="?sort=newest">Newest</a>
<a href="?sort=best"><b>Best</b></a>
{{/equal}}
</div>
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{tag.Background}}');">
<div class="flex flex-col items-center justify-center text-center">
<h2 class="text-2xl font-bold">{{tag.Display}}</h2>
<p>{{tag.PostCount}} posts</p>
</div>
<div class="flex flex-col">
{{#equal tag.Sort "popular"}}
<a href="?sort=popular"><b>Popular</b></a>
<a href="?sort=newest">Newest</a>
<a href="?sort=best">Best</a>
{{/equal}}
{{#equal tag.Sort "newest"}}
<a href="?sort=popular">Popular</a>
<a href="?sort=newest"><b>Newest</b></a>
<a href="?sort=best">Best</a>
{{/equal}}
{{#equal tag.Sort "best"}}
<a href="?sort=popular">Popular</a>
<a href="?sort=newest">Newest</a>
<a href="?sort=best"><b>Best</b></a>
{{/equal}}
</div>
</header>
<main>
<div class="posts">
{{#each tag.Posts}}
{{> partials/post }}
{{/each}}
</div>
<div class="pageSelector">
<div class="mt-4 font-bold">
{{#if displayPrev}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/if}}

View File

@ -5,33 +5,30 @@
<title>{{user.Username}} - rimgo</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/user.css" />
</head>
<body>
{{> partials/header }}
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');">
<div class="flex items-center gap-2">
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
<div>
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
</div>
</div>
<p class="mt-2">{{user.Bio}}</p>
</header>
<main>
<div class="userMeta" style="background-image: url('{{user.Cover}}');">
<div class="flex flex-center-y gap-2">
<img class="pfp" src="{{user.Avatar}}" width="72" height="72">
<div>
<h2>{{user.Username}}</h2>
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
</div>
</div>
<p>{{user.Bio}}</p>
</div>
<div class="posts">
{{#each submissions}}
{{> partials/post }}
{{/each}}
</div>
<div class="pageSelector">
<div class="mt-4 font-bold">
{{#equal page "0" }}
{{else}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>