...
 
Commits (3)
......@@ -166,6 +166,21 @@ experience on various platforms.
with controls for the playing track(s) and other information like
the artist, album and title.
### Theme
The thekno colors are configurable and are specified with an array containing
three numbers from 0 to 255 representing the colors red, green and blue.
`theme.primary`:
The primary color used for primary buttons and other interaction points in
the app.
`theme.accent`:
The accent color especially used for headings.
`theme.base`:
The base color that is particularly used for the main and panel backgrounds.
## Example Configuration
```json
......@@ -266,6 +281,11 @@ experience on various platforms.
"mediaSession": {
"fallbackArtwork": "https://thek.lohro.de/~local/media-session-bg.png"
}
},
"theme": {
"primary": [42, 154, 152],
"accent": [247, 146, 16],
"base": [33, 37, 41]
}
}
```
......@@ -8,6 +8,7 @@
<meta property="google" content="notranslate">
<link rel="icon" href="">
<link rel="manifest" href="/~local/manifest.json">
<link rel="stylesheet" href="/~local/theme.css">
<title>thekno</title>
</head>
<body>
......@@ -15,7 +16,7 @@
<strong>We're sorry but thekno doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<style type="text/css">body{display:flex;align-items:center;justify-content:center;background:#24242e;width:100vw;height:100vh;padding:0!important;margin:0!important;overflow:hidden}h1{text-align:center;margin:0}h1 span{position:relative;transform:translateY(20px);display:inline-block;animation:bounce .6s ease infinite alternate;font-family:-system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,Helvetica,Arial,sans-serif;font-size:1.25em;line-height:1;color: #cc6633;text-shadow:0 3px 4px rgba(0,0,0,.14),0 3px 3px rgba(0,0,0,.12),0 1px 8px rgba(0,0,0,.2);letter-spacing:.075em} h1 span:nth-child(2){animation-delay:.1s} h1 span:nth-child(3){animation-delay:.2s} h1 span:nth-child(4){animation-delay:.3s} h1 span:nth-child(5){animation-delay:.4s} h1 span:nth-child(6){animation-delay:.5s} @keyframes bounce{100%{transform:translateY(-20px)}}</style>
<style type="text/css">body{display:flex;align-items:center;justify-content:center;background:var(--theme-base);width:100vw;height:100vh;padding:0!important;margin:0!important;overflow:hidden}h1{text-align:center;margin:0}h1 span{position:relative;transform:translateY(20px);display:inline-block;animation:bounce .6s ease infinite alternate;font-family:-system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,Helvetica,Arial,sans-serif;font-size:1.25em;line-height:1;color:var(--theme-accent);text-shadow:0 3px 4px rgba(0,0,0,.14),0 3px 3px rgba(0,0,0,.12),0 1px 8px rgba(0,0,0,.2);letter-spacing:.075em}h1 span:nth-child(2){animation-delay:.1s}h1 span:nth-child(3){animation-delay:.2s}h1 span:nth-child(4){animation-delay:.3s}h1 span:nth-child(5){animation-delay:.4s}h1 span:nth-child(6){animation-delay:.5s}@keyframes bounce{100%{transform:translateY(-20px)}}</style>
<h1></h1>
<script>var h=document.querySelector('h1');h.innerHTML=document.title.split('').map(function(c){return '<span>'+c+'</span>'}).join('')</script>
</div>
......
#!/bin/dash
# Helper util for generating branded thekno apps.
# thekno-chameleon uses thekno’s environment configuration to produce a PWA
# manifest and other assets.
set -eu
if [ "$#" -ne 3 ]; then
......@@ -26,7 +30,7 @@ fi
ENV_FILE=$1
BASE_URL=$2
DEST_DIR=$(realpath "$3")
THEME_COLOR="#24242e"
THEME_COLOR="#005500"
LOGO_URL=$(jq -r '.integration.logo' "$ENV_FILE")
LOGO="$DEST_DIR/$(basename "$LOGO_URL")"
......@@ -35,8 +39,112 @@ SHORT_NAME=$(jq -r '.integration.shortName' "$ENV_FILE")
BACKGROUND_COLOR=$(jq -r ".integration.splashBackground // \"$THEME_COLOR\"" "$ENV_FILE")
DESCRIPTION=$(jq -r '.description' "$ENV_FILE")
mkdir -p "$DEST_DIR"
wget -q -O "$LOGO" "$LOGO_URL"
THEME_COLOR_PRIMARY=$(jq -r '.theme.primary' "$ENV_FILE")
THEME_COLOR_ACCENT=$(jq -r '.theme.accent' "$ENV_FILE")
THEME_COLOR_BASE=$(jq -r '.theme.base' "$ENV_FILE")
# Converts a rgb color to hsl.
# Based on https://gist.github.com/vahidk/05184faf3d92a0aa1b46aeaa93b07786
rgb_to_hsl() {
local red=$1
local green=$2
local blue=$3
bc <<-EOF
scale=4
define max_num(r, g, b) {
if (r >= g && r >= b) return r
if (g >= r && g >= b) return g
return b
}
define min_num(r, g, b) {
if (r <= g && r <= b) return r
if (g <= r && g <= b) return g
return b
}
define abs(a) {
if (a < 0) return (-a)
return a
}
define calc_h(d, max, r, g, b) {
if (d == 0) return 0
if (max == r) {
part = (g - b) / d
scale = 0
result = part % 6
scale = 4
return result
}
if (max == g) return (b - r) / d + 2
if (max == b) return (r - g) / d + 4
}
red=$red
green=$green
blue=$blue
red /= 255
green /= 255
blue /= 255
max = max_num(red, green, blue)
min = min_num(red, green, blue)
d = max - min
h = calc_h(d, max, red, green, blue)
l = (min + max) / 2
if (d == 0) s = 0
if (d != 0) s = d / (1 - abs(2 * l - 1))
h*60
s
l
EOF
}
# Takes a float to round and a number indicating to how many decimal places the
# float should be rounded.
# From https://askubuntu.com/a/179949
round_num() {
echo $(printf %.$2f $(echo "scale=$2;(((10^$2)*$1)+0.5)/(10^$2)" | bc))
}
# Converts a number <= 1 into its percentage representation.
to_percent() {
echo $(round_num $(echo "$1 * 100" | bc -l) 0)
}
# Generates the css code for a single theme entry. Takes the entry name, red,
# green, blue, hue, saturation, lightness.
gen_theme_entry() {
name=$1
r=$2
g=$3
b=$4
h=$(round_num $5 0)
s=$(to_percent $6)
l=$(to_percent $7)
cat <<EOF
--theme-$name-rgb: rgb($r, $g, $b);
--theme-$name-base: $h, $s%;
--theme-$name-lightness: $l%;
--theme-$name: hsl(var(--theme-$name-base), var(--theme-$name-lightness));
EOF
}
download_logo() {
local output
if ! output=$(wget -O "$LOGO" "$LOGO_URL" 2>&1); then
echo "$output"
echo ""
echo "Failed to download logo from $LOGO_URL."
echo "Make sure the file exist and is accessible or change the path in your thekno-env file."
exit 1
fi
}
render_image() {
local src dest format size
......@@ -70,6 +178,24 @@ render_logo() {
} | jo -a
}
mkdir -p "$DEST_DIR"
mapfile -t THEME_COLOR_ACCENT_HSL < <(rgb_to_hsl $(echo "$THEME_COLOR_ACCENT" | jq -r '.[]'))
mapfile -t THEME_COLOR_PRIMARY_HSL < <(rgb_to_hsl $(echo "$THEME_COLOR_PRIMARY" | jq -r '.[]'))
mapfile -t THEME_COLOR_BASE_HSL < <(rgb_to_hsl $(echo "$THEME_COLOR_BASE" | jq -r '.[]'))
cat <<-EOF > "$DEST_DIR/theme.css"
:root {
$(gen_theme_entry "primary" $(echo "$THEME_COLOR_PRIMARY" | jq -r '.[]') ${THEME_COLOR_PRIMARY_HSL[*]})
$(gen_theme_entry "accent" $(echo "$THEME_COLOR_ACCENT" | jq -r '.[]') ${THEME_COLOR_ACCENT_HSL[*]})
$(gen_theme_entry "base" $(echo "$THEME_COLOR_BASE" | jq -r '.[]') ${THEME_COLOR_BASE_HSL[*]})
}
EOF
download_logo
jo \
name="$NAME" \
short_name="$SHORT_NAME" \
......@@ -83,12 +209,12 @@ jo \
orientation=portrait-primary >"$DEST_DIR/manifest.json"
cat <<-EOF >&2
Logo files and PWA manifest have been generated in the "$DEST_DIR" directory.
Please add the following section to your NGINX configuration:
Logo files, theme stylesheet and PWA manifest have been generated in the "$DEST_DIR" directory.
Please add the following section to your NGINX configuration:
EOF
cat <<-EOF
cat <<EOF
location /~local/ {
alias "$DEST_DIR/";
add_header Cache-Control "public, no-cache";
......
@import '../assets/fonts/fonts.css';
@import './variables.scss';
@import './base.scss';
@import './util.scss';
// The colors used in this app are defined below. Use the hsl representation for
// lighten, darken and other modifications, like so:
//
......@@ -15,22 +10,29 @@
// hsl(var(--color-accent-base), calc(var(--color-accent-lightness) - 25%));
:root {
--color-primary-hex: #2a9a98;
--color-primary-base: 179, 57%;
--color-primary-lightness: 38%;
// Merge the theme colors (starting with --theme-) with the default colors.
--color-primary-rgb: var(--theme-primary-rgb, rgb(32, 160, 160));
--color-primary-base: var(--theme-primary-base, 180, 67%);
--color-primary-lightness: var(--theme-primary-lightness, 38%);
--color-primary: hsl(var(--color-primary-base), var(--color-primary-lightness));
--color-accent-hex: #cc6633;
--color-accent-base: 20, 60%;
--color-accent-lightness: 50%;
--color-accent-rgb: var(--theme-accent-rgb, rgb(0, 85, 0));
--color-accent-base: var(--theme-accent-base, 120, 100%);
--color-accent-lightness: var(--theme-accent-lightness, 17%);
--color-accent: hsl(var(--color-accent-base), var(--color-accent-lightness));
--color-base-hex: #24242e;
--color-base-base: 240, 12%;
--color-base-lightness: 16%;
--color-base-rgb: var(--theme-base-rgb, rgb(34, 34, 34));
--color-base-base: var(--theme-base-base, 0, 0%);
--color-base-lightness: var(--theme-base-lightness, 13%);
--color-base: hsl(var(--color-base-base), var(--color-base-lightness));
--color-surface-base: var(--color-base-base);
--color-surface-lightness: calc(var(--color-base-lightness) + 7.5%);
--color-surface: hsl(var(--color-surface-base), var(--color-surface-lightness));
}
@import '../assets/fonts/fonts.css';
@import './variables.scss';
@import './base.scss';
@import './util.scss';