omakase/views/index.go
2025-07-24 19:31:03 -03:00

218 lines
5.9 KiB
Go

package view
import (
_ "embed"
"fmt"
"goreader/gallery"
"goreader/state"
"strconv"
"strings"
"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(fmt.Sprintf("javascript:filter_tags('%s')", strings.TrimSpace(t.Name) /* FIXME */)).
Class("tag")
{
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.Name])).Class("name", backgroundClass)
}
return d
}
func artistTag(artistName string) *gtag.Tag {
d := gtag.New("a").
Href(fmt.Sprintf("javascript:filter_artist('%s')", artistName /* FIXME */)).
Class("tag")
{
d.Tag("span").Text(artistName).Class("name")
}
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 {
thumb := thumbnail(fmt.Sprintf("/page/%s/1", g.Uuid()))
return gtag.Div().Id("image-wrapper").Append(thumb)
}
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").
Tag("h1").
SetAttr("style", "color: white; margin: 10px 0 10px 0;").
Text(g.Name())
d.Tag("h2").Style("margin: 0").Text(g.JpName())
d.Tag("h3").
Text(fmt.Sprintf("Pages: %d", len(g.Images()))).
Style("font-size: 14px; ; margin: 0;")
d.Tag("h2").Text("Artists")
artists := d.Div()
{
for _, a := range g.Artists() {
artists.Append(artistTag(a))
}
}
d.Tag("h2").Text("Tags")
tags := d.Div()
{
for _, t := range g.Tags() {
tags.Append(tag(t, state))
}
}
}
return d
}
func cover(g gallery.Gallery) *gtag.Tag {
var s []string
for _, tag := range g.Tags() {
s = append(s, fmt.Sprintf("'%s'", strings.TrimSpace(tag.Name)) /* FIXME */)
}
dataset := fmt.Sprintf("[%s]", strings.Join(s, ", "))
a := gtag.New("a").
Class("cover").
Id(fmt.Sprintf("cover-%s", g.Uuid())).
SetAttr("href", fmt.Sprintf("/read/%s", g.Uuid())).
SetAttr("data-tags", dataset).
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 = 70
func SearchResults(galleries []gallery.Gallery) *gtag.Tag {
s := gtag.New("section")
results := s.Tag("section").Id("results")
{
results.Tag("header").Tag("h1").Text(fmt.Sprintf("Listing %d Galleries", len(galleries)))
covers := results.Tag("main")
for _, g := range galleries {
covers.Append(cover(g))
}
}
return s
}
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.Tag("a").
Href("javascript:clear_filters()").
Text("clear filters")
nav.Div().Text("omakase v1")
}
center := body.Div().Id("center")
{
d := center.Div()
// HTMX faz com que isso receba [InspectorInfo] quando usuário paira o
// mouse sobre algum cover
d.Tag("section").Id("inspector")
d.Append(SearchResults(state.Galleries))
}
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))
// }