From ceebf34874eeb27bb56a31d9b3e96269d8938b14 Mon Sep 17 00:00:00 2001 From: Svilen Markov <7613769+svilenmarkov@users.noreply.github.com> Date: Wed, 23 Apr 2025 13:03:18 +0100 Subject: [PATCH] Use hex values & add theme_color in manifest.json It looks like support for hsl color values within the manifest is limited so we have to convert the colors to hex --- internal/glance/config-fields.go | 4 ++ internal/glance/config.go | 1 + internal/glance/glance.go | 12 +++--- internal/glance/templates/document.html | 2 +- internal/glance/templates/manifest.json | 1 + internal/glance/utils.go | 56 +++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/internal/glance/config-fields.go b/internal/glance/config-fields.go index f3a1649..5ca6fb6 100644 --- a/internal/glance/config-fields.go +++ b/internal/glance/config-fields.go @@ -32,6 +32,10 @@ func (c *hslColorField) String() string { return fmt.Sprintf("hsl(%.1f, %.1f%%, %.1f%%)", c.Hue, c.Saturation, c.Lightness) } +func (c *hslColorField) ToHex() string { + return hslToHex(c.Hue, c.Saturation, c.Lightness) +} + func (c *hslColorField) UnmarshalYAML(node *yaml.Node) error { var value string diff --git a/internal/glance/config.go b/internal/glance/config.go index 2053ff9..ea67f5f 100644 --- a/internal/glance/config.go +++ b/internal/glance/config.go @@ -39,6 +39,7 @@ type config struct { Theme struct { BackgroundColor *hslColorField `yaml:"background-color"` + BackgroundColorAsHex string `yaml:"-"` PrimaryColor *hslColorField `yaml:"primary-color"` PositiveColor *hslColorField `yaml:"positive-color"` NegativeColor *hslColorField `yaml:"negative-color"` diff --git a/internal/glance/glance.go b/internal/glance/glance.go index 903cfbc..d2fad40 100644 --- a/internal/glance/glance.go +++ b/internal/glance/glance.go @@ -96,6 +96,12 @@ func newApplication(config *config) (*application, error) { config.Theme.CustomCSSFile = app.resolveUserDefinedAssetPath(config.Theme.CustomCSSFile) config.Branding.LogoURL = app.resolveUserDefinedAssetPath(config.Branding.LogoURL) + if config.Theme.BackgroundColor != nil { + config.Theme.BackgroundColorAsHex = config.Theme.BackgroundColor.ToHex() + } else { + config.Theme.BackgroundColorAsHex = "#151519" + } + if config.Branding.FaviconURL == "" { config.Branding.FaviconURL = app.StaticAssetPath("favicon.png") } else { @@ -111,11 +117,7 @@ func newApplication(config *config) (*application, error) { } if config.Branding.AppBackgroundColor == "" { - config.Branding.AppBackgroundColor = ternary( - config.Theme.BackgroundColor != nil, - config.Theme.BackgroundColor.String(), - "hsl(240, 8%, 9%)", - ) + config.Branding.AppBackgroundColor = config.Theme.BackgroundColorAsHex } var manifestWriter bytes.Buffer diff --git a/internal/glance/templates/document.html b/internal/glance/templates/document.html index 26beab9..4530827 100644 --- a/internal/glance/templates/document.html +++ b/internal/glance/templates/document.html @@ -11,7 +11,7 @@ - + diff --git a/internal/glance/templates/manifest.json b/internal/glance/templates/manifest.json index eae4d19..124f330 100644 --- a/internal/glance/templates/manifest.json +++ b/internal/glance/templates/manifest.json @@ -2,6 +2,7 @@ "name": "{{ .App.Config.Branding.AppName }}", "display": "standalone", "background_color": "{{ .App.Config.Branding.AppBackgroundColor }}", + "theme_color": "{{ .App.Config.Branding.AppBackgroundColor }}", "scope": "/", "start_url": "/", "icons": [ diff --git a/internal/glance/utils.go b/internal/glance/utils.go index a614bda..2f76965 100644 --- a/internal/glance/utils.go +++ b/internal/glance/utils.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "html/template" + "math" "net/http" "net/url" "os" @@ -182,3 +183,58 @@ func ternary[T any](condition bool, a, b T) T { // Having compile time errors about unused variables is cool and all, but I don't want to // have to constantly comment out my code while I'm working on it and testing things out func ItsUsedTrustMeBro(...any) {} + +func hslToHex(h, s, l float64) string { + s /= 100.0 + l /= 100.0 + + var r, g, b float64 + + if s == 0 { + r, g, b = l, l, l + } else { + hueToRgb := func(p, q, t float64) float64 { + if t < 0 { + t += 1 + } + if t > 1 { + t -= 1 + } + if t < 1.0/6.0 { + return p + (q-p)*6.0*t + } + if t < 1.0/2.0 { + return q + } + if t < 2.0/3.0 { + return p + (q-p)*(2.0/3.0-t)*6.0 + } + return p + } + + q := 0.0 + if l < 0.5 { + q = l * (1 + s) + } else { + q = l + s - l*s + } + + p := 2*l - q + + h /= 360.0 + + r = hueToRgb(p, q, h+1.0/3.0) + g = hueToRgb(p, q, h) + b = hueToRgb(p, q, h-1.0/3.0) + } + + ir := int(math.Round(r * 255.0)) + ig := int(math.Round(g * 255.0)) + ib := int(math.Round(b * 255.0)) + + ir = int(math.Max(0, math.Min(255, float64(ir)))) + ig = int(math.Max(0, math.Min(255, float64(ig)))) + ib = int(math.Max(0, math.Min(255, float64(ib)))) + + return fmt.Sprintf("#%02x%02x%02x", ir, ig, ib) +}