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
This commit is contained in:
Svilen Markov 2025-04-23 13:03:18 +01:00
parent efd39e1f80
commit ceebf34874
6 changed files with 70 additions and 6 deletions

View File

@ -32,6 +32,10 @@ func (c *hslColorField) String() string {
return fmt.Sprintf("hsl(%.1f, %.1f%%, %.1f%%)", c.Hue, c.Saturation, c.Lightness) 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 { func (c *hslColorField) UnmarshalYAML(node *yaml.Node) error {
var value string var value string

View File

@ -39,6 +39,7 @@ type config struct {
Theme struct { Theme struct {
BackgroundColor *hslColorField `yaml:"background-color"` BackgroundColor *hslColorField `yaml:"background-color"`
BackgroundColorAsHex string `yaml:"-"`
PrimaryColor *hslColorField `yaml:"primary-color"` PrimaryColor *hslColorField `yaml:"primary-color"`
PositiveColor *hslColorField `yaml:"positive-color"` PositiveColor *hslColorField `yaml:"positive-color"`
NegativeColor *hslColorField `yaml:"negative-color"` NegativeColor *hslColorField `yaml:"negative-color"`

View File

@ -96,6 +96,12 @@ func newApplication(config *config) (*application, error) {
config.Theme.CustomCSSFile = app.resolveUserDefinedAssetPath(config.Theme.CustomCSSFile) config.Theme.CustomCSSFile = app.resolveUserDefinedAssetPath(config.Theme.CustomCSSFile)
config.Branding.LogoURL = app.resolveUserDefinedAssetPath(config.Branding.LogoURL) 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 == "" { if config.Branding.FaviconURL == "" {
config.Branding.FaviconURL = app.StaticAssetPath("favicon.png") config.Branding.FaviconURL = app.StaticAssetPath("favicon.png")
} else { } else {
@ -111,11 +117,7 @@ func newApplication(config *config) (*application, error) {
} }
if config.Branding.AppBackgroundColor == "" { if config.Branding.AppBackgroundColor == "" {
config.Branding.AppBackgroundColor = ternary( config.Branding.AppBackgroundColor = config.Theme.BackgroundColorAsHex
config.Theme.BackgroundColor != nil,
config.Theme.BackgroundColor.String(),
"hsl(240, 8%, 9%)",
)
} }
var manifestWriter bytes.Buffer var manifestWriter bytes.Buffer

View File

@ -11,7 +11,7 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="{{ .App.Config.Branding.AppName }}"> <meta name="apple-mobile-web-app-title" content="{{ .App.Config.Branding.AppName }}">
<meta name="theme-color" content="{{ if ne nil .App.Config.Theme.BackgroundColor }}{{ .App.Config.Theme.BackgroundColor }}{{ else }}hsl(240, 8%, 9%){{ end }}"> <meta name="theme-color" content="{{ .App.Config.Theme.BackgroundColorAsHex }}">
<link rel="apple-touch-icon" sizes="512x512" href='{{ .App.Config.Branding.AppIconURL }}'> <link rel="apple-touch-icon" sizes="512x512" href='{{ .App.Config.Branding.AppIconURL }}'>
<link rel="manifest" href='{{ .App.VersionedAssetPath "manifest.json" }}'> <link rel="manifest" href='{{ .App.VersionedAssetPath "manifest.json" }}'>
<link rel="icon" type="image/png" href="{{ .App.Config.Branding.FaviconURL }}" /> <link rel="icon" type="image/png" href="{{ .App.Config.Branding.FaviconURL }}" />

View File

@ -2,6 +2,7 @@
"name": "{{ .App.Config.Branding.AppName }}", "name": "{{ .App.Config.Branding.AppName }}",
"display": "standalone", "display": "standalone",
"background_color": "{{ .App.Config.Branding.AppBackgroundColor }}", "background_color": "{{ .App.Config.Branding.AppBackgroundColor }}",
"theme_color": "{{ .App.Config.Branding.AppBackgroundColor }}",
"scope": "/", "scope": "/",
"start_url": "/", "start_url": "/",
"icons": [ "icons": [

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"html/template" "html/template"
"math"
"net/http" "net/http"
"net/url" "net/url"
"os" "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 // 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 // have to constantly comment out my code while I'm working on it and testing things out
func ItsUsedTrustMeBro(...any) {} 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)
}