omakase/views/index.go
2025-07-03 17:12:05 -03:00

256 lines
7.1 KiB
Go

package view
import (
_ "embed"
"fmt"
"goreader/gallery"
"goreader/state"
"strconv"
"github.com/silva-guimaraes/gtag"
)
//go:embed static/styles.css
var styles string
//go:embed static/reader.js
var readerJavascript string
//go:embed static/index.js
var indexJavascript string
//go:embed static/hotkeys.min.js
var hotkeys string
//go:embed static/htmx.min.js
var htmx string
func tag(t gallery.Tag, state *state.State) *gtag.Tag {
gender := "X"
backgroundClass := "any"
if t.Sex == gallery.Male {
gender = "M"
backgroundClass = "male"
}
if t.Sex == gallery.Female {
gender = "F"
backgroundClass = "female"
}
d := gtag.New("a").
Href("javascript:void(0)").
Class("tag").
SetAttr("hx-post", fmt.Sprintf("/filter/%s/%s", t.Name, t.Sex)).
SetAttr("hx-target", "#listing").
SetAttr("hx-swap", "outerHTML")
{
d.Tag("span").Text(gender).Class("name", backgroundClass)
d.Tag("span").Text(t.Name).Class("name")
d.Tag("span").Text(strconv.Itoa(state.UniqueTags[t])).Class("name", backgroundClass)
}
return d
}
func thumbnail(src string) *gtag.Tag {
return gtag.NewVoid("img").SetAttr("src", src).SetAttr("loading", "lazy")
}
func fullThumbnail(g gallery.Gallery) *gtag.Tag {
return thumbnail(fmt.Sprintf("/page/%s/1", g.Uuid()))
}
func smallThumbnail(g gallery.Gallery) *gtag.Tag {
return thumbnail(fmt.Sprintf("/thumb/%s", g.Uuid())).Class("thumbnail")
}
func InspectorInfo(g gallery.Gallery, state *state.State) *gtag.Tag {
d := gtag.Div().Class("float")
{
// d.Append(smallThumbnail(g))
d.Append(fullThumbnail(g))
// d.Tag("div").Id("inspector-image-placeholder")
d.Tag("a").
SetAttr("href", fmt.Sprintf("/read/%s", g.Uuid())).
SetAttr("hx-boost", "false").
SetAttr("style", "color: white").
Tag("h1").Text(g.Name())
d.Tag("h2").Text(g.JpName())
tags := d.Div()
{
for _, t := range g.Tags() {
tags.Append(tag(t, state))
}
}
}
return d
}
func cover(g gallery.Gallery) *gtag.Tag {
a := gtag.New("a").
Class("cover").
Id(fmt.Sprintf("cover-%s", g.Uuid())).
SetAttr("href", fmt.Sprintf("/read/%s", g.Uuid())).
SetAttr("hx-get", fmt.Sprintf("/details/%s", g.Uuid())).
SetAttr("onmouseenter", "inspectSetTimeout(event)").
SetAttr("onmouseleave", "inspectClearTimeout(event)").
SetAttr("hx-trigger", "inspect").
SetAttr("hx-target", "#inspector").
SetAttr("hx-boost", "false")
a.Append(smallThumbnail(g))
return a
}
const galleriesPerPage = 50
func SearchResults(galleries []gallery.Gallery, page int) *gtag.Tag {
glm := max(len(galleries)-1, 0)
recent := galleries[min(page*galleriesPerPage, glm):min((page+1)*galleriesPerPage, glm)]
m := gtag.New("main")
// HTMX faz com que isso receba [InspectorInfo] quando usuário paira o
// mouse sobre algum cover
m.Tag("section").Id("inspector")
results := m.Tag("section").Id("results")
{
for _, g := range recent {
results.Append(cover(g))
}
}
return m
}
func Stats(state *state.State) *gtag.Tag {
s := gtag.New("div").Id("stats")
{
s.Tag("p").Text(fmt.Sprintf("Galleries loaded: %d", len(state.Galleries)))
s.Tag("p").Text(fmt.Sprintf("Unique tags: %d", len(state.UniqueTags)))
s.Tag("p").Text(fmt.Sprintf("Unique artists: %d", len(state.UniqueArtists)))
s.Tag("p").Text(fmt.Sprintf("Unique groups: %d", len(state.UniqueGroups)))
s.Tag("p").Text(fmt.Sprintf("Unique parodies: %d", len(state.UniqueParodies)))
}
if !state.Done {
s.SetAttr("hx-get", "/stats").SetAttr("hx-trigger", "every 0.01s").SetAttr("hx-swap", "outerHTML")
}
return s
}
func Index(state *state.State, page int) *gtag.Tag {
html := gtag.Doc()
{
head := html.Head()
{
head.Tag("title").Text("index")
head.Tag("style").Asis(styles)
head.Asis(
`<link href='https://fonts.googleapis.com/css?family=Noto Sans' rel='stylesheet'>`,
)
head.Asis("<!-- hotkeys -->")
head.Tag("script").Asis(hotkeys)
head.Asis("<!-- htmx -->")
head.Tag("script").Asis(htmx)
}
body := html.Body().Id("index").SetAttr("hx-boost", "true")
{
nav := body.Tag("nav").Class("container")
{
nav.Div().Text("omakase v1")
}
center := body.Div().Id("center")
{
top := center.Tag("div").Class("top")
{
top.Div().Id("search-bar").VoidTag("input").
Class("ask-input").
SetAttr("type", "search").
SetAttr("name", "search").
SetAttr("autocomplete", "false").
SetAttr("placeholder", "Slash to search...").
SetAttr("hx-post", "/search").
SetAttr("hx-trigger", "input changed delay:50ms, search").
SetAttr("hx-target", "#search-results")
header := top.Tag("header").Class("container")
{
header.Div().Id("omakase").
Tag("a").
SetAttr("href", "/random").
Text("おまかせ").
SetAttr("target", "_blank")
header.Tag("hr").Style("opacity: 0.2;")
header.Append(Stats(state))
}
}
ret := center.Tag("main").Id("search-results")
{
controls := ret.Tag("section").AddClass("container").Id("controls")
{
paging := controls.Div()
{
maxPages := len(state.Galleries) / galleriesPerPage
previousPage := gtag.New("a").
AddClass("page-control").
Text("<")
if page > 1 {
previousPage.SetAttr("href",
fmt.Sprintf("?page=%d", page-1),
)
}
paging.Append(previousPage)
p := page
for ; p < min(page+3, maxPages); p++ {
paging.Tag("a").
AddClass("page-control").
SetAttr("href",
fmt.Sprintf("?page=%d", p),
).Text(fmt.Sprint(p))
}
if len(state.Galleries) > 0 && p != maxPages {
paging.Tag("span").Text("...")
}
paging.Tag("a").
AddClass("page-control").
SetAttr("href",
fmt.Sprintf("?page=%d", maxPages),
).Text(fmt.Sprint(maxPages))
nextPage := gtag.New("a").
AddClass("page-control").
SetAttr("href", "?page=1").
Text(">")
if page < maxPages {
nextPage.SetAttr("href",
fmt.Sprintf("?page=%d", page+1),
)
} else if page == maxPages {
nextPage.SetAttr("disabled", "true")
}
paging.Append(nextPage)
}
}
ret.Append(SearchResults(state.Galleries, page))
}
}
body.Tag("footer").P().Text(randomQuote())
body.Tag("script").Asis(indexJavascript)
}
}
return html
}
// content := body.Div().Id("content").Class("container"); {
// details := content.Tag("details"); {
// details.Tag("summary").Text("filter tags...")
// tags := details.Div().Id("tags"); {
// tags.Tag("a").Href("javascript:void(0)").Text("clear tags").
// Class("name", "tag").Style("display: block;").
// SetAttr("hx-post", "/filter/clear/all").
// SetAttr("hx-target", "#listing").
// SetAttr("hx-swap", "outerHTML")
// tags.Text("Tags:")
// tagsSpan := tags.Tag("span").SetAttr("hx-boost", "true"); {
// for k, v := range uniqueTags {
// tagsSpan.Append(tag(k, v))
// }
// }
// }
// }
// content.Append(galleriesListing(galleries))
// }