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)
+}