From 7c7d637af91f99a39640e6be69a677cdac0efbb5 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Sun, 17 Aug 2025 22:56:22 +0700 Subject: feat: add theme wheel --- static/input.css | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'static/input.css') diff --git a/static/input.css b/static/input.css index 131faa9..00ac12f 100644 --- a/static/input.css +++ b/static/input.css @@ -248,6 +248,52 @@ body:has(.lg-container:not([class~="lg-inline"])) #sidebar { -webkit-text-stroke-width: 0.1vw; } +.theme-wheel { + position: fixed; + width: 15vmax; + height: 15vmax; + border-radius: 50%; + background: var(--background-light-color); + opacity: 0.8; + border: 1vmax outset var(--background-dark-color); + box-shadow: 0 0 5vmax var(--main-light-color); + opacity: 0; + visibility: hidden; + transform: scale(0.5); + transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + z-index: 1001; +} + +.theme-wheel.active { + opacity: 1; + visibility: visible; + transform: scale(1); +} + +.theme-icon { + position: absolute; + width: 4vmax; + height: 4vmax; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + border: 0.1vmax inset var(--background-light-color); + background: var(--interlocked-hexagons-background); + background-size: contain; +} + +.theme-icon:hover { + transform: scale(1.2); +} + +.theme-icon.active { + transform: scale(1.2); + border: 0.3vmax outset var(--main-light-color); +} + .lg-backdrop { background-color: var(--background-light-color); opacity: 0.8 !important; -- cgit v1.3.1+13 From 49a64e91e76b5970007c0be22b74942fee11df8a Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Mon, 18 Aug 2025 12:32:54 +0700 Subject: feat: add map page --- internal/b2/client.go | 1 + internal/frontmatter/parser.go | 1 - locale/localization.en.yaml | 2 + locale/localization.go | 5 + locale/localization.ru.yaml | 2 + main.go | 67 +++++++++++ static/input.css | 17 +-- views/layouts/general-page.html | 2 +- views/pages/blog-page.html | 10 +- views/pages/global-map.html | 241 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 328 insertions(+), 20 deletions(-) create mode 100644 views/pages/global-map.html (limited to 'static/input.css') diff --git a/internal/b2/client.go b/internal/b2/client.go index 5322b84..7b745a8 100644 --- a/internal/b2/client.go +++ b/internal/b2/client.go @@ -84,6 +84,7 @@ func (c *B2Client) Scan(prefix string) ([]*BlogPage, error) { PublishedTime: publishedTime, Thumbnail: attrs.Info["thumbnail"], Tags: strings.Split(attrs.Info["tags"], ","), + Geolocation: attrs.Info["geolocation"], }, }) } diff --git a/internal/frontmatter/parser.go b/internal/frontmatter/parser.go index 3c00a7f..1a521c0 100644 --- a/internal/frontmatter/parser.go +++ b/internal/frontmatter/parser.go @@ -16,7 +16,6 @@ type Metadata struct { Thumbnail string `yaml:"thumbnail"` Tags []string `yaml:"tags"` Geolocation string `yaml:"geolocation"` - Timezone string `yaml:"timezone"` } func ParseFrontmatter(content []byte) (metadata *Metadata, markdown []byte, err error) { diff --git a/locale/localization.en.yaml b/locale/localization.en.yaml index 879fce8..f5ee6c9 100644 --- a/locale/localization.en.yaml +++ b/locale/localization.en.yaml @@ -7,3 +7,5 @@ BlogSearch: ActionDateOrdered: 'Action Date' PublicationDateOrdered: 'Publication Date' ChooseAllTags: 'Choose All' +GlobalMap: + Header: 'Global Map' diff --git a/locale/localization.go b/locale/localization.go index d5c6b48..56b6462 100644 --- a/locale/localization.go +++ b/locale/localization.go @@ -10,6 +10,7 @@ import ( type LocaleConfig struct { TagsLabel string `yaml:"TagsLabel" json:"TagsLabel"` BlogSearch BlogSearchConfig `yaml:"BlogSearch" json:"BlogSearch"` + GlobalMap GlobalMapConfig `yaml:"GlobalMap" json:"GlobalMap"` } type BlogSearchConfig struct { @@ -22,6 +23,10 @@ type BlogSearchConfig struct { ChooseAllTags string `yaml:"ChooseAllTags" json:"ChooseAllTags"` } +type GlobalMapConfig struct { + Header string `yaml:"Header" json:"Header"` +} + func LoadConfig(path string, config *LocaleConfig) error { fileBytes, err := os.ReadFile(path) if err != nil { diff --git a/locale/localization.ru.yaml b/locale/localization.ru.yaml index 786665d..c236d1e 100644 --- a/locale/localization.ru.yaml +++ b/locale/localization.ru.yaml @@ -7,3 +7,5 @@ BlogSearch: ActionDateOrdered: 'дате действия' PublicationDateOrdered: 'времени публикации' ChooseAllTags: 'Выбрать все' +GlobalMap: + Header: 'Глобальная карта' diff --git a/main.go b/main.go index 9e3f9a4..e07ca6b 100644 --- a/main.go +++ b/main.go @@ -83,6 +83,7 @@ func main() { {Name: "blog-catalogue", Files: []string{"views/layouts/general-page.html", "views/pages/blog-catalogue.html"}}, {Name: "index", Files: []string{"views/index.html"}}, {Name: "catalogue-blog-cards", Files: []string{"views/partials/catalogue-blog-cards.html", "views/partials/catalogue-blog-card-tags.html"}}, + {Name: "global-map", Files: []string{"views/pages/global-map.html"}}, }) if err != nil { slog.Error("fail to initialize template manager", slog.String("error", err.Error())) @@ -112,6 +113,72 @@ func main() { return c.Type("html").Send(content) }) + app.Get("/:lang/map", func(c *fiber.Ctx) error { + lang := c.Params("lang") + if !slices.Contains(availableLanguages, lang) { + c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8) + return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang)) + } + + pages, err := b2Client.Scan(lang + "/") + status := fiber.StatusOK + if err != nil { + status = fiber.StatusPartialContent + pages = []*b2.BlogPage{} + } + + type MapMarker struct { + Title string `json:"Title"` + PageLink string `json:"PageLink"` + Lat float64 `json:"Lat"` + Long float64 `json:"Long"` + AccuracyMeters int64 `json:"AccuracyMeters"` + Thumbnail string `json:"Thumbnail"` + } + + mapMarkers := make([]*MapMarker, 0, len(pages)) + for _, page := range pages { + geolocationParts := strings.Split(page.Metadata.Geolocation, " ") + if len(geolocationParts) < 2 { + continue + } + + var x, y float64 + var areaError int64 + if len(geolocationParts) >= 2 { + x, _ = strconv.ParseFloat(geolocationParts[0], 64) + y, _ = strconv.ParseFloat(geolocationParts[1], 64) + } + if len(geolocationParts) >= 3 { + areaError, _ = strconv.ParseInt(geolocationParts[2], 10, 64) + } + + mapMarkers = append(mapMarkers, &MapMarker{ + Title: page.Metadata.Title, + PageLink: fmt.Sprintf("/%s/blog/%s", lang, page.FileName), + Lat: x, + Long: y, + AccuracyMeters: areaError, + Thumbnail: page.Metadata.Thumbnail, + }) + } + + content, err := tm.Render("global-map", fiber.Map{ + "Lang": lang, + "L": localization[lang], + "MapLocationLat": 45.4507, + "MapLocationLong": 68.8319, + "MapMarkers": mapMarkers, + }) + if err != nil { + slog.Warn("failed to generate page", slog.String("page", "/"+lang+"/map"), slog.String("error", err.Error())) + c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8) + return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate page") + } + + return c.Type("html").Status(status).Send(content) + }) + app.Get("/:lang/blog", func(c *fiber.Ctx) error { lang := c.Params("lang") if !slices.Contains(availableLanguages, lang) { diff --git a/static/input.css b/static/input.css index 00ac12f..0d6e786 100644 --- a/static/input.css +++ b/static/input.css @@ -1,17 +1,6 @@ @import "tailwindcss"; @theme { - --color-olive-dark: #4b513a; - --color-olive-medium: #8a9d8a; - --color-olive-light: #a5b8a5; - --color-cream-dark: #ffffdd; - --color-cream-light: #fffff0; - --color-lettuce-dark: #384a0c; - --color-lettuce-medium: #9bb665; - --color-lettuce-light: #bbd095; - --color-sunny-dark: #f5eee2; - --color-sunny-light: #fff93f; - --font-spectral: Spectral, serif; --font-patua: "Patua One", cursive; } @@ -109,16 +98,16 @@ a:hover { color: var(--main-light-color) !important; } -#location-map { +#map-container { color: var(--leaflet-text-color) !important; } -#location-map a { +#map-container a { color: var(--leaflet-link-color) !important; text-decoration: underline; } -#location-map a:hover { +#map-container a:hover { color: var(--leaflet-link-hover-color) !important; text-decoration: underline; } diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index d2e74fa..5918956 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -44,7 +44,7 @@
- +
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html index 330a1ac..755744d 100644 --- a/views/pages/blog-page.html +++ b/views/pages/blog-page.html @@ -19,7 +19,7 @@ {{ .ParsedMarkdown }} {{- if .MapLocationX }}
-
+

{{- end }}
@@ -33,8 +33,10 @@ diff --git a/views/pages/global-map.html b/views/pages/global-map.html new file mode 100644 index 0000000..cbb6c7d --- /dev/null +++ b/views/pages/global-map.html @@ -0,0 +1,241 @@ + + + + + + SAYA TODAY // {{ .L.GlobalMap.Header }} + + + + + {{ block "header" . }}{{ end }} + + + + + + + + + + + + +
+ + + + + + + + + {{ block "footer" . }}{{ end }} + + + -- cgit v1.3.1+13 From f089ba2435eb4a54ab4e6b2c20d91d0c9f872a2d Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Mon, 18 Aug 2025 17:01:53 +0700 Subject: refactor: more line height in gallery captions feat: fixate gallery divs to viewport measures feat: make thumbnails square feat: remove recreating gallery on window resize --- internal/lightgallery/html_renderer.go | 20 +++++--------------- static/input.css | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'static/input.css') diff --git a/internal/lightgallery/html_renderer.go b/internal/lightgallery/html_renderer.go index 7ecad44..849759e 100644 --- a/internal/lightgallery/html_renderer.go +++ b/internal/lightgallery/html_renderer.go @@ -83,15 +83,15 @@ func (r *LightGalleryHTMLRenderer) renderLightGallery(w util.BufWriter, source [ thumb: "https://f003.backblazeb2.com/file/sayana-photos/webp-320p/%s.webp", subHtml: `+"`"+``+"`"+` }`, img.URL, img.URL, util.EscapeHTML(captionHTML), imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, captionHTML, dayDate.Format("2006-01-02 15:04:05 -07:00"))) } w.WriteString(fmt.Sprintf(` `, galleryID, galleryID, strings.Join(dynamicElements, ","), galleryID, galleryID, galleryID, galleryID, galleryID, galleryID)) +document.addEventListener('DOMContentLoaded', createLightGallery%s); +`, galleryID, galleryID, strings.Join(dynamicElements, ","), galleryID)) } return ast.WalkContinue, nil diff --git a/static/input.css b/static/input.css index 0d6e786..8c0069b 100644 --- a/static/input.css +++ b/static/input.css @@ -323,14 +323,21 @@ body:has(.lg-container:not([class~="lg-inline"])) #sidebar { } .lg-content { - top: 3vmax !important; + top: 2.5vmax !important; + bottom: calc(10vmin + 5vmax) !important; +} + +.lg-thumb-item { + width: 10vmin !important; + height: 10vmin !important; } .lg-container:not([class~="lg-inline"]) .lg-content { top: 4vmax !important; } -.lg-toolbar .lg-icon { +.lg-toolbar .lg-icon, +.lg-content .lg-icon { padding: 0 0.7vmax; font-size: 1.5vmax !important; height: 1.5vmax; @@ -338,11 +345,20 @@ body:has(.lg-container:not([class~="lg-inline"])) #sidebar { color: var(--main-dark-color); } -.lg-container:not([class~="lg-inline"]) .lg-toolbar .lg-icon { +.lg-container:not([class~="lg-inline"]) .lg-toolbar .lg-icon, +.lg-container:not([class~="lg-inline"]) .lg-content .lg-icon { font-size: 3vmax !important; height: 3vmax; } +.lg-prev { + left: 0 !important; +} + +.lg-next { + right: 0 !important; +} + .lg-toolbar .lg-icon:hover { color: var(--main-medium-color); } @@ -362,7 +378,7 @@ body:has(.lg-container:not([class~="lg-inline"])) #sidebar { .inline-gallery-container { width: 80%; - height: 60vmin; + height: 70vmin; } .light-gallery-captions { -- cgit v1.3.1+13