Files
fnx_web/webcontroller/user_style.go

500 lines
13 KiB
Go
Raw Normal View History

2018-01-07 21:42:19 +01:00
package webcontroller
import (
2022-01-17 17:40:03 +01:00
"bytes"
2018-01-07 21:42:19 +01:00
"fmt"
2022-01-17 17:40:03 +01:00
"html/template"
"math/rand"
2018-01-07 21:42:19 +01:00
"net/http"
2022-01-17 17:40:03 +01:00
"time"
2018-01-07 21:42:19 +01:00
)
2022-02-07 12:00:22 +01:00
func userStyleFromRequest(r *http.Request) (s pixeldrainStyleSheet) {
2021-11-28 15:58:04 +01:00
// Get the chosen style from the URL
var style = r.URL.Query().Get("style")
2018-01-07 21:42:19 +01:00
2021-11-28 15:58:04 +01:00
// If the URL style was empty use the cookie value
if style == "" {
if cookie, err := r.Cookie("style"); err == nil {
style = cookie.Value
2018-07-11 22:46:44 +02:00
}
}
2018-01-07 21:42:19 +01:00
2022-02-07 12:00:22 +01:00
return userStyle(style)
}
func userStyle(style string) (s pixeldrainStyleSheet) {
2021-11-28 15:58:04 +01:00
switch style {
case "classic":
2022-01-25 20:37:21 +01:00
s = pixeldrainClassicStyle
2021-11-28 15:58:04 +01:00
case "solarized_dark":
2022-01-25 20:37:21 +01:00
s = solarizedDarkStyle
2021-11-28 15:58:04 +01:00
case "sunny":
2022-01-25 20:37:21 +01:00
s = sunnyPixeldrainStyle
2021-11-28 15:58:04 +01:00
case "maroon":
2022-01-25 20:37:21 +01:00
s = maroonStyle
2021-11-28 15:58:04 +01:00
case "hacker":
2022-01-25 20:37:21 +01:00
s = hackerStyle
2021-11-28 15:58:04 +01:00
case "canta":
2022-01-25 20:37:21 +01:00
s = cantaPixeldrainStyle
2021-11-28 15:58:04 +01:00
case "deepsea":
2022-01-25 20:37:21 +01:00
s = deepseaPixeldrainStyle
2022-01-10 21:59:07 +01:00
case "skeuos":
2022-01-25 20:37:21 +01:00
s = skeuosPixeldrainStyle
2022-01-17 15:46:59 +01:00
case "nord":
2022-01-25 20:37:21 +01:00
s = nordPixeldrainStyle
2022-01-17 17:40:03 +01:00
case "snowstorm":
2022-01-25 20:37:21 +01:00
s = snowstormPixeldrainStyle
2022-03-08 23:34:10 +01:00
case "sweet":
s = sweetPixeldrainStyle
2021-11-28 15:58:04 +01:00
case "default":
fallthrough // use default case
default:
2022-01-25 20:37:21 +01:00
s = defaultPixeldrainStyle
2021-11-28 15:58:04 +01:00
}
2022-01-25 20:37:21 +01:00
// Set default colors
var noColor = hsl{0, 0, 0}
var setDefault = func(color *hsl, def hsl) {
if *color == noColor {
*color = def
}
}
setDefault(&s.Link, s.Highlight.Add(0, 0, -.05))
setDefault(&s.InputDisabled, s.Input.Add(0, -.2, -.2))
setDefault(&s.ScrollbarForeground, s.Input)
setDefault(&s.ScrollbarHover, s.ScrollbarForeground.Add(0, 0, .1))
setDefault(&s.Layer1Text, s.Text)
setDefault(&s.Chart1, s.Highlight)
setDefault(&s.Chart2, s.Chart1.Add(120, 0, 0))
setDefault(&s.Chart3, s.Chart2.Add(120, 0, 0))
return s
2019-12-23 23:56:57 +01:00
}
2022-03-08 23:34:10 +01:00
type Colour interface {
CSS() string
}
2019-12-23 23:56:57 +01:00
type pixeldrainStyleSheet struct {
2022-01-17 17:40:03 +01:00
Text hsl
Link hsl // Based on Highlight if undefined
Input hsl // Buttons, text fields
InputText hsl
2022-01-18 20:58:57 +01:00
InputDisabled hsl
2022-01-17 17:40:03 +01:00
Highlight hsl // Links, highlighted buttons, list navigation
HighlightText hsl // Text on buttons
Danger hsl
ScrollbarForeground hsl // Based on Highlight if undefined
ScrollbarHover hsl // Based on ScrollbarForeground if undefined
Layer1 hsl // Deepest and darkest layer
Layer1Text hsl // Based on Text if undefined
Layer2 hsl
Layer3 hsl
Layer4 hsl // Highest and brightest layer
2022-01-25 20:37:21 +01:00
// Colors to use in graphs
Chart1 hsl
Chart2 hsl
Chart3 hsl
2022-01-17 17:40:03 +01:00
Shadow hsl
Light bool // If this is a light theme
2019-12-23 23:56:57 +01:00
}
func (s pixeldrainStyleSheet) String() string {
return fmt.Sprintf(
2018-01-07 21:42:19 +01:00
`:root {
2022-03-08 23:34:10 +01:00
--text_color: %s;
--link_color: %s;
--input_color: %s;
--input_color_dark: %s;
--input_text_color: %s;
--input_disabled_color: %s;
--highlight_color: %s;
--highlight_color_dark: %s;
--highlight_text_color: %s;
--danger_color: %s;
--danger_color_dark: %s;
--scrollbar_foreground_color: %s;
--scrollbar_hover_color: %s;
--scrollbar_background_color: %s;
--layer_1_color: %s;
--layer_1_color_border: %s;
--layer_1_text_color: %s;
--layer_2_color: %s;
--layer_2_color_border: %s;
--layer_3_color: %s;
--layer_3_color_border: %s;
--layer_4_color: %s;
--layer_4_color_border: %s;
--chart_1_color: %s;
--chart_2_color: %s;
--chart_3_color: %s;
--shadow_color: %s;
}`,
2022-03-08 23:34:10 +01:00
s.Text.CSS(),
s.Link.CSS(),
s.Input.CSS(),
s.Input.Add(0, 0, -.02).CSS(),
s.InputText.CSS(),
s.InputDisabled.CSS(),
s.Highlight.CSS(),
s.Highlight.Add(0, 0, -.02).CSS(),
s.HighlightText.CSS(),
s.Danger.CSS(),
s.Danger.Add(0, 0, -.02).CSS(),
s.ScrollbarForeground.CSS(),
s.ScrollbarHover.CSS(),
s.Layer2.CSS(), // Scrollbar background
s.Layer1.CSS(),
s.Layer1.Add(0, 0, .05).CSS(),
s.Layer1Text.CSS(),
s.Layer2.CSS(),
s.Layer2.Add(0, 0, .05).CSS(),
s.Layer3.CSS(),
s.Layer3.Add(0, 0, .05).CSS(),
s.Layer4.CSS(),
s.Layer4.Add(0, 0, .05).CSS(),
s.Chart1.CSS(),
s.Chart2.CSS(),
s.Chart3.CSS(),
s.Shadow.CSS(),
2022-01-17 17:40:03 +01:00
)
}
func (s pixeldrainStyleSheet) Background(tpl *template.Template) template.URL {
var (
now = time.Now()
month = now.Month()
day = now.Day()
file string
2019-12-23 23:56:57 +01:00
)
2022-01-17 17:40:03 +01:00
if now.Weekday() == time.Wednesday && rand.Intn(20) == 0 {
file = "checker_wednesday"
} else if month == time.August && day == 8 {
file = "checker_dwarf"
} else if month == time.August && day == 24 {
file = "checker_developers"
} else if month == time.October && day == 31 {
file = "checker_halloween"
} else if month == time.December && (day == 25 || day == 26 || day == 27) {
file = "checker_christmas"
} else {
2022-03-08 23:34:10 +01:00
// file = "checker_ukraine"
file = fmt.Sprintf("checker%d", now.UnixNano()%18)
2022-01-17 17:40:03 +01:00
}
if s.Light {
file += "_light"
}
var buf = bytes.Buffer{}
if err := tpl.ExecuteTemplate(&buf, file+".png", nil); err != nil {
panic(err)
}
return template.URL(buf.String())
2018-01-07 21:42:19 +01:00
}
2018-07-11 22:46:44 +02:00
2019-02-18 22:42:20 +01:00
type hsl struct {
2018-07-11 22:46:44 +02:00
Hue int
Saturation float64
Lightness float64
}
2020-01-13 16:24:06 +01:00
func (orig hsl) RGB() string {
var r, g, b, q, p float64
var h, s, l = float64(orig.Hue) / 360, orig.Saturation, orig.Lightness
if s == 0 {
r, g, b = l, l, l
} else {
var hue2rgb = func(p, q, t float64) float64 {
if t < 0 {
t++
}
if t > 1 {
t--
}
if t < 1.0/6.0 {
return p + (q-p)*6*t
} else if t < 1.0/2.0 {
return q
} else if t < 2.0/3.0 {
return p + (q-p)*(2.0/3.0-t)*6
}
return p
}
if l < 0.5 {
q = l * (1 + s)
} else {
q = l + s - l*s
}
p = 2*l - q
r = hue2rgb(p, q, h+1.0/3.0)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h-1.0/3.0)
}
return fmt.Sprintf("%02x%02x%02x", int(r*255), int(g*255), int(b*255))
}
2022-03-08 23:34:10 +01:00
func (orig hsl) CSS() string {
return "#" + orig.RGB()
}
2020-01-13 16:24:06 +01:00
2018-07-11 22:46:44 +02:00
// Add returns a NEW HSL struct, it doesn't modify the current one
2022-01-10 21:59:07 +01:00
func (h hsl) Add(hue int, saturation float64, lightness float64) hsl {
2019-02-18 22:42:20 +01:00
var new = hsl{
h.Hue + hue,
h.Saturation + saturation,
h.Lightness + lightness,
2018-07-11 22:46:44 +02:00
}
// Hue bounds correction
if new.Hue < 0 {
new.Hue += 360
} else if new.Hue > 360 {
new.Hue -= 360
}
// Saturation bounds check
if new.Saturation < 0 {
new.Saturation = 0
} else if new.Saturation > 1 {
new.Saturation = 1
}
// Lightness bounds check
if new.Lightness < 0 {
new.Lightness = 0
} else if new.Lightness > 1 {
new.Lightness = 1
}
return new
}
// Following are all the available styles
2019-02-18 22:42:20 +01:00
var defaultPixeldrainStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .8},
Input: hsl{266, .85, .38},
InputText: hsl{0, 0, 1},
Highlight: hsl{117, .63, .46},
HighlightText: hsl{0, 0, 0},
Danger: hsl{357, .63, .46},
ScrollbarForeground: hsl{266, .85, .40},
ScrollbarHover: hsl{266, .85, .50},
Layer1: hsl{275, .8, .07},
Layer2: hsl{275, .75, .12},
Layer3: hsl{275, .7, .18},
Layer4: hsl{275, .65, .24},
Shadow: hsl{0, 0, 0},
2021-06-17 11:27:31 +02:00
}
var pixeldrainClassicStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .8},
Input: hsl{0, 0, .25},
InputText: hsl{0, 0, 1},
Highlight: hsl{89, .60, .45},
HighlightText: hsl{0, 0, 0},
Danger: hsl{339, .65, .31},
ScrollbarForeground: hsl{0, 0, .40},
ScrollbarHover: hsl{0, 0, .50},
Layer1: hsl{0, 0, .08},
Layer2: hsl{0, 0, .11},
Layer3: hsl{0, 0, .15},
Layer4: hsl{0, 0, .18},
Shadow: hsl{0, 0, 0},
2019-07-06 18:41:16 +02:00
}
var sunnyPixeldrainStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .1},
Input: hsl{0, 0, .96}, // hsl(0, 0%, 96%)
InputText: hsl{0, 0, .1},
Highlight: hsl{89, .74, .5}, // hsl(89, 73%, 50%)
HighlightText: hsl{0, 0, 0},
Danger: hsl{345, .99, .33}, // hsl(345, 99%, 33%)
ScrollbarForeground: hsl{0, 0, .30},
ScrollbarHover: hsl{0, 0, .40},
Layer1: hsl{0, 0, .98}, // hsl(0, 0%, 13%)
Layer2: hsl{0, 1, 1},
Layer3: hsl{0, 1, 1},
Layer4: hsl{0, 1, 1},
Shadow: hsl{0, 0, 0},
2019-02-18 22:42:20 +01:00
}
var solarizedDarkStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .75},
Input: hsl{192, .95, .25},
InputText: hsl{0, 0, 1},
Highlight: hsl{145, .63, .42},
HighlightText: hsl{0, 0, 0},
Danger: hsl{343, .63, .42},
ScrollbarForeground: hsl{192, .95, .30},
ScrollbarHover: hsl{192, .95, .40},
Layer1: hsl{192, .87, .09},
Layer2: hsl{192, .81, .14},
Layer3: hsl{192, .95, .17},
Layer4: hsl{192, .99, .19},
Shadow: hsl{0, 0, 0},
2018-07-11 22:46:44 +02:00
}
2019-02-18 22:42:20 +01:00
var maroonStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .8},
Input: hsl{0, .87, .40}, // hsl(0, 87%, 40%)
InputText: hsl{0, 0, 1},
Highlight: hsl{137, 1, .37}, //hsl(137, 100%, 37%)
HighlightText: hsl{0, 0, 0},
Danger: hsl{9, .96, .42}, //hsl(9, 96%, 42%)
ScrollbarForeground: hsl{0, .75, .3},
ScrollbarHover: hsl{0, .75, .4},
Layer1: hsl{0, .7, .05},
Layer2: hsl{0, .8, .08}, // hsl{0, .8, .15},
Layer3: hsl{0, .9, .14},
Layer4: hsl{0, .9, .20},
Shadow: hsl{0, 0, 0},
2018-07-11 22:46:44 +02:00
}
2019-03-31 21:06:52 +02:00
var hackerStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .8},
Input: hsl{120, .5, .1}, // hsl(120, 50%, 10%)
InputText: hsl{0, 0, 1},
Highlight: hsl{120, 1, .5},
HighlightText: hsl{0, 0, 0},
Danger: hsl{0, 1, .4},
ScrollbarForeground: hsl{120, .5, .25},
ScrollbarHover: hsl{120, .5, .35},
Layer1: hsl{0, 0, 0},
Layer2: hsl{0, 0, .03},
Layer3: hsl{120, .3, .08},
Layer4: hsl{120, .5, .12},
Shadow: hsl{0, 0, 0},
2019-07-06 18:41:16 +02:00
}
var cantaPixeldrainStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .8},
Input: hsl{167, .06, .30}, // hsl(167, 6%, 30%)
InputText: hsl{0, 0, 1},
Highlight: hsl{165, 1, .40}, // hsl(165, 100%, 40%)
HighlightText: hsl{0, 0, 0},
Danger: hsl{40, 1, .5}, // hsl(40, 100%, 50%)
ScrollbarForeground: hsl{204, .05, .78}, // hsl(204, 5%, 78%)
ScrollbarHover: hsl{204, .05, .88},
Layer1: hsl{180, .04, .16},
Layer2: hsl{168, .05, .21},
Layer3: hsl{170, .05, .26},
Layer4: hsl{163, .04, .31},
Shadow: hsl{0, 0, 0},
2019-03-31 21:06:52 +02:00
}
2019-07-16 22:07:10 +02:00
2019-09-18 22:23:12 +02:00
var deepseaPixeldrainStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{0, 0, .7},
Input: hsl{41, .58, .47},
InputText: hsl{0, 0, 0},
Highlight: hsl{5, .77, .55},
HighlightText: hsl{0, 0, 0},
Danger: hsl{5, .77, .55},
ScrollbarForeground: hsl{162, .28, .23}, // hsl(162, 28%, 23%)
ScrollbarHover: hsl{12, .38, .26}, // hsl(12, 38%, 26%)
Layer1: hsl{160, .27, .05},
Layer2: hsl{163, .26, .09}, // hsl(163, 26%, 11%)
Layer3: hsl{161, .28, .12}, // hsl(161, 28%, 14%)
Layer4: hsl{161, .32, .15},
Shadow: hsl{0, 0, 0},
2019-07-16 22:07:10 +02:00
}
2022-01-10 21:59:07 +01:00
var skeuosPixeldrainStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{60, .06, .93}, // hsl(60, 6%, 93%)
Input: hsl{226, .15, .23}, //hsl(226, 15%, 23%)
InputText: hsl{60, .06, .93},
Highlight: hsl{282, .65, .54}, // hsl(282, 65%, 54%)
HighlightText: hsl{0, 0, 1},
Danger: hsl{0, .79, .43}, // hsl(0, 79%, 43%)
ScrollbarForeground: hsl{220, .02, .62}, // hsl(220, 2%, 62%)
ScrollbarHover: hsl{220, .02, .80},
Layer1: hsl{232, .14, .11}, //hsl(232, 14%, 11%)
Layer2: hsl{229, .14, .16}, // hsl(229, 14%, 16%)
Layer3: hsl{225, .14, .17}, // hsl(225, 14%, 17%)
Layer4: hsl{226, .14, .18}, // hsl(226, 14%, 18%)
Shadow: hsl{0, 0, 0},
2022-01-10 21:59:07 +01:00
}
2022-01-17 15:46:59 +01:00
var nordPixeldrainStyle = pixeldrainStyleSheet{
2022-01-17 17:40:03 +01:00
Text: hsl{210, .34, .63},
Input: hsl{193, .43, .67},
InputText: hsl{180, .19, .23},
Highlight: hsl{145, .63, .42},
HighlightText: hsl{0, 0, 0},
Danger: hsl{354, .42, .56},
ScrollbarForeground: hsl{193, .43, .67},
ScrollbarHover: hsl{193, .43, .76},
Layer1: hsl{220, .16, .22},
Layer2: hsl{222, .16, .28},
Layer3: hsl{220, .17, .32},
Layer4: hsl{220, .16, .36},
Shadow: hsl{0, 0, 0},
}
var snowstormPixeldrainStyle = pixeldrainStyleSheet{
Text: hsl{220, .16, .36}, // hsl(220, 16%, 36%)
2022-01-18 20:58:57 +01:00
Link: hsl{92, .40, .40},
2022-01-17 17:40:03 +01:00
Input: hsl{193, .43, .67}, // hsl(193, 43%, 67%)
InputText: hsl{180, .19, .23},
Highlight: hsl{92, .28, .65}, // hsl(92, 28%, 65%)
HighlightText: hsl{0, 0, 0},
Danger: hsl{354, .42, .56},
ScrollbarForeground: hsl{193, .43, .67},
ScrollbarHover: hsl{193, .43, .76},
2022-01-18 20:58:57 +01:00
Layer1: hsl{220, .17, .32}, // hsl(220, 17%, 32%)
2022-01-17 17:40:03 +01:00
Layer1Text: hsl{219, .28, .88},
Layer2: hsl{219, .28, .88}, // hsl(219, 28%, 88%)
Layer3: hsl{218, .27, .92}, // hsl(218, 27%, 92%)
Layer4: hsl{218, .27, .94}, // hsl(218, 27%, 94%)
2022-03-01 20:47:15 +01:00
Shadow: hsl{0, .0, .50},
2022-01-17 17:40:03 +01:00
Light: true,
2022-01-17 15:46:59 +01:00
}
2022-03-08 23:34:10 +01:00
var sweetPixeldrainStyle = pixeldrainStyleSheet{
Text: hsl{223, .13, .79}, // hsl(223, 13%, 79%)
Input: hsl{214, .26, .20}, // hsl(214, 26%, 12%)
InputText: hsl{223, .13, .79},
Highlight: hsl{296, .88, .44},
HighlightText: hsl{0, 0, 0},
Danger: hsl{356, 1, .64}, // hsl(356, 100%, 64%)
Layer1: hsl{225, .25, .06}, // hsl(225, 25%, 6%)
Layer2: hsl{228, .25, .12}, // hsl(228, 25%, 12%)
Layer3: hsl{229, .25, .14}, // hsl(229, 25%, 14%)
Layer4: hsl{229, .25, .18},
Shadow: hsl{0, 0, 0},
}