Theming changes

This commit is contained in:
2022-06-07 14:43:01 +02:00
parent aed4c3b301
commit 6bed9e9374
96 changed files with 649 additions and 495 deletions

14
go.mod
View File

@@ -1,27 +1,27 @@
module fornaxian.tech/pixeldrain_web
go 1.17
go 1.18
replace fornaxian.tech/pixeldrain_api_client => ../pixeldrain_api_client
require (
fornaxian.tech/config v0.0.0-20211108212237-6133aed90586
fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640
fornaxian.tech/pixeldrain_api_client v0.0.0-20220305171318-e1197ab3d4c0
fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787
fornaxian.tech/pixeldrain_api_client v0.0.0-20220503161309-06b62641c05d
fornaxian.tech/util v0.0.0-20220603201140-7b74b1181b98
github.com/julienschmidt/httprouter v1.3.0
github.com/microcosm-cc/bluemonday v1.0.18
github.com/russross/blackfriday/v2 v2.1.0
)
require (
github.com/BurntSushi/toml v1.0.0 // indirect
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/gocql/gocql v0.0.0-20220224095938-0eacd3183625 // indirect
github.com/gocql/gocql v1.1.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
)

35
go.sum
View File

@@ -1,13 +1,11 @@
fornaxian.tech/config v0.0.0-20211108212237-6133aed90586 h1:/4a0Iq3cYeyTWcPHsN9pVAGJH3UTq1GapK253lHfXnE=
fornaxian.tech/config v0.0.0-20211108212237-6133aed90586/go.mod h1:ULIXF4J1DbBw4EsIPRNQDf6J3hl4P/jlihjy6UCm9FM=
fornaxian.tech/log v0.0.0-20190617093801-1c7ce9a7c9b3/go.mod h1:OyWUNsNPlo5AmlOHvJ4s6WcStQw+9rQyBMwmTz0buEM=
fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640 h1:UPDxJwLRCfh/cv80UMSanzmZ0jIcfS1mcd0Y06HYuLw=
fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640/go.mod h1:sN82qMToeHhP2u3ehvrcE8y1IudRZJAZO9yG5OBYblo=
fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787 h1:9ujI8Qi6+FTL/YW6xQAS9DmWDMerHBe8foQvVD/G/i0=
fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787/go.mod h1:FqVgfghmxTGR3l9Zx4MOMeZ9KHjiEFl3s3C0BSTvBwk=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
fornaxian.tech/util v0.0.0-20220603201140-7b74b1181b98 h1:d0FsJgwiHunT4X6Hyz7FRBQF+ix/RDagKj2/2VnlY14=
fornaxian.tech/util v0.0.0-20220603201140-7b74b1181b98/go.mod h1:lCmtcb4/SVt2ol55/EHDWGySY7o0ONbj97RR9CdsN4M=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
@@ -15,9 +13,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCS
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/gocql/gocql v0.0.0-20220224095938-0eacd3183625 h1:6ImvI6U901e1ezn/8u2z3bh1DZIvMOia0yTSBxhy4Ao=
github.com/gocql/gocql v0.0.0-20220224095938-0eacd3183625/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/gocql/gocql v1.1.0 h1:ow36yzymDGsuKqnkecq2zR3prFkkbdzC/af5zTyPXNc=
github.com/gocql/gocql v1.1.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -39,27 +36,15 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

View File

@@ -122,5 +122,7 @@ this.
So enable IPv6. If you don't have IPv6, call your ISP and ask them why not.
<div style="margin-top: 100px; height: 128px; text-align: center;">
<a href="https://sia.tech/">{{ template "built-with-Sia-mono.svg" . }}</a>
<a href="https://sia.tech/">
<img style="height: 100%;" src="/res/img/misc/built-with-Sia-mono.svg" alt="Built with Sia"/>
</a>
</div>

View File

@@ -1,87 +0,0 @@
function renderFileButton(apiURL, id, title, subtitle) {
let btn = document.createElement("a")
btn.classList = "file_button"
btn.href = "/u/" + id
btn.target = "_blank"
let thumbnail = document.createElement("img")
thumbnail.src = apiURL + "/file/" + id + "/thumbnail?width=80&height=80"
thumbnail.alt = title
let titleSpan = document.createElement("span")
titleSpan.classList = "file_button_title"
titleSpan.innerText = title
let br = document.createElement("br")
let subtitleSpan = document.createElement("span")
subtitleSpan.classList = "file_button_subtitle"
subtitleSpan.innerText = subtitle
btn.appendChild(thumbnail)
btn.appendChild(titleSpan)
btn.appendChild(br)
btn.appendChild(subtitleSpan)
return btn
}
function getCookie(name) {
var result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie)
return result ? result[1] : null
}
function printDate(date, hours, minutes, seconds) {
let dateStr = date.getFullYear()
+ "-" + ("00" + (date.getMonth() + 1)).slice(-2)
+ "-" + ("00" + date.getDate()).slice(-2)
if (hours) { dateStr += " " + ("00" + date.getHours()).slice(-2) }
if (minutes) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
if (seconds) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
return dateStr
}
// Get the uploads from localstorage
let uploadsStr = localStorage.getItem("uploaded_files")
if (uploadsStr === null) { uploadsStr = "" }
let uploads = Array()
if (uploadsStr != "") {
// Strip the trailing comma
uploads = uploadsStr.slice(0, -1).split(",")
}
// Get the uploads from a cookie
uploadsStr = getCookie("pduploads")
if (uploadsStr === null) { uploadsStr = "" }
if (uploadsStr != "") {
uploadsStr = uploadsStr.slice(0, -1) // Strip the trailing dot
uploads.push(uploadsStr.split(".").reverse())
}
// Render all the items
function getHistoryItem() {
let item = uploads.shift()
if (item === undefined || item === "") { return }
fetch(
apiEndpoint + "/file/" + item + "/info"
).then(resp => {
if (!resp.ok) {
return Promise.reject()
}
return resp.json()
}).then(resp => {
document.getElementById("uploaded_files").appendChild(
renderFileButton(
apiEndpoint,
resp.id,
resp.name,
printDate(new Date(resp.date_upload), true, true, true),
)
)
getHistoryItem()
}).catch(err => {
console.log("Fetch failed: " + err)
getHistoryItem()
})
}
getHistoryItem()

View File

Before

Width:  |  Height:  |  Size: 92 B

After

Width:  |  Height:  |  Size: 92 B

View File

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 279 B

View File

Before

Width:  |  Height:  |  Size: 111 B

After

Width:  |  Height:  |  Size: 111 B

View File

Before

Width:  |  Height:  |  Size: 132 B

After

Width:  |  Height:  |  Size: 132 B

View File

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 336 B

View File

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 124 B

View File

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 328 B

View File

Before

Width:  |  Height:  |  Size: 128 B

After

Width:  |  Height:  |  Size: 128 B

View File

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 289 B

View File

Before

Width:  |  Height:  |  Size: 151 B

After

Width:  |  Height:  |  Size: 151 B

View File

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 313 B

View File

Before

Width:  |  Height:  |  Size: 161 B

After

Width:  |  Height:  |  Size: 161 B

View File

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 366 B

View File

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 248 B

View File

Before

Width:  |  Height:  |  Size: 455 B

After

Width:  |  Height:  |  Size: 455 B

View File

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 167 B

View File

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 371 B

View File

Before

Width:  |  Height:  |  Size: 108 B

After

Width:  |  Height:  |  Size: 108 B

View File

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

View File

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

View File

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 114 B

View File

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 133 B

View File

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

View File

Before

Width:  |  Height:  |  Size: 116 B

After

Width:  |  Height:  |  Size: 116 B

View File

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 320 B

View File

Before

Width:  |  Height:  |  Size: 127 B

After

Width:  |  Height:  |  Size: 127 B

View File

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 331 B

View File

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 122 B

View File

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 326 B

View File

Before

Width:  |  Height:  |  Size: 120 B

After

Width:  |  Height:  |  Size: 120 B

View File

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 324 B

View File

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 118 B

View File

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 322 B

View File

Before

Width:  |  Height:  |  Size: 138 B

After

Width:  |  Height:  |  Size: 138 B

View File

Before

Width:  |  Height:  |  Size: 343 B

After

Width:  |  Height:  |  Size: 343 B

View File

Before

Width:  |  Height:  |  Size: 203 B

After

Width:  |  Height:  |  Size: 203 B

View File

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 442 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 379 B

View File

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 195 B

View File

Before

Width:  |  Height:  |  Size: 187 B

After

Width:  |  Height:  |  Size: 187 B

View File

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

View File

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 633 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -72,12 +72,13 @@ body {
background: var(--background);
min-height: 100vh;
padding: 0;
transition: opacity 0.2s;
}
header,
footer,
.checkers {
background-image: url("{{.BackgroundPattern}}");
background-image: var(--background_pattern);
background-color: var(--background_pattern_color);
background-repeat: repeat;
}

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Not Found"}}
{{template "user_style" .}}
</head>
<body>

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "451, Unavailable For Legal Reasons"}}
{{template "user_style" .}}
</head>
<body>

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "500, Internal Server Error"}}
{{template "user_style" .}}
</head>
<body>

View File

@@ -4,7 +4,6 @@
{{if and .Authenticated .User.IsAdmin}}
<head>
{{template "meta_tags" "Administrator panel"}}
{{template "user_style" .}}
<script>
window.api_endpoint = '{{.APIEndpoint}}';
@@ -20,7 +19,6 @@
{{else}}
<head>
{{template "meta_tags" "Administrator panel"}}
{{template "user_style" .}}
</head>
<body>
{{template "page_top" .}}

View File

@@ -2,7 +2,7 @@
<html lang="en">
<head>
{{template "meta_tags" "Appearance settings"}}
{{template "user_style" .}}
<link id="stylesheet_theme_2" rel="stylesheet" type="text/css" href="/theme.css"/>
</head>
<body>
@@ -24,6 +24,8 @@
<input type="radio" id="style_nord_dark" name="style"><label for="style_nord_dark">Nord dark</label>
<br/>
<input type="radio" id="style_nord_light" name="style"><label for="style_nord_light">Nord light</label>
<!-- <br/>
Hue: <input id="hue" type="number" min="0" max="360" placeholder="0"/><br/> -->
<br/>
<br/>
<input type="radio" id="style_solarized" name="style"><label for="style_solarized">Solarized</label>
@@ -50,30 +52,56 @@
<br/>
Other (experimental) themes
<br/>
<input type="radio" id="style_maroon" name="style"><label for="style_maroon">Maroon Style</label>
<input type="radio" id="style_maroon" name="style"><label for="style_maroon">Maroon Style</label>
<br/>
<input type="radio" id="style_hacker" name="style"><label for="style_hacker">Hacker Style</label>
<input type="radio" id="style_hacker" name="style"><label for="style_hacker">Hacker Style</label>
<br/>
<input type="radio" id="style_canta" name="style"><label for="style_canta">Canta Style</label>
<input type="radio" id="style_canta" name="style"><label for="style_canta">Canta Style</label>
(Inspired by <a href="https://github.com/vinceliuice/Canta-theme" target="_blank">Canta GTK</a>)
<br/>
<input type="radio" id="style_skeuos" name="style"><label for="style_skeuos">Skeuos Style</label>
<input type="radio" id="style_skeuos" name="style"><label for="style_skeuos">Skeuos Style</label>
(Inspired by <a href="https://www.gnome-look.org/p/1441725/" target="_blank">Skeuos GTK</a>)
<br/>
<input type="radio" id="style_sweet" name="style"><label for="style_sweet">Sweet</label>
<input type="radio" id="style_sweet" name="style"><label for="style_sweet">Sweet</label>
</div>
</section>
<script>
let style = "nord"
let hue = -1
// Style selector
document.getElementsByName("style").forEach(function(elem) {
elem.addEventListener("change", function(evt){
var date = new Date();
date.setTime(date.getTime() + (10 * 365 * 24 * 60 * 60 * 1000));
document.cookie = "style=" + evt.target.id.substring(6) + "; expires=" + date.toUTCString() + "; path=/";
location.reload();
elem.addEventListener("change", e => {
style = e.target.id.substring(6)
setStyle()
})
});
document.getElementById("hue").addEventListener("change", e => {
hue = e.target.value
setStyle()
})
function setStyle() {
var date = new Date();
date.setTime(date.getTime() + (10 * 365 * 24 * 60 * 60 * 1000));
document.cookie = "style="+style+"; expires=" + date.toUTCString() + "; path=/"
if (hue >= 0 && hue <= 360) {
document.cookie = "hue="+hue+"; expires=" + date.toUTCString() + "; path=/"
}
let stylesheet1 = document.getElementById("stylesheet_theme")
let stylesheet2 = document.getElementById("stylesheet_theme_2")
// First load the sheet in the secondary tag, wait for it to load,
// and replace the original sheet when it has finished loading
stylesheet2.href= "/theme.css?style="+style+"&hue="+hue
stylesheet2.onload = e => {
stylesheet1.href= "/theme.css?style="+style+"&hue="+hue
}
}
</script>
{{template "page_bottom" .}}
{{template "analytics"}}

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Apps"}}
{{template "user_style" .}}
<style>
.specs {

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Directory upload"}}
{{template "user_style" . }}
<script>
window.api_endpoint = '{{.APIEndpoint}}';

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "E-mail verification"}}
{{template "user_style" .}}
</head>
<body>
{{template "page_top" .}}

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "404, File Not Found"}}
{{template "user_style" .}}
</head>
<body>
@@ -44,7 +43,6 @@
<html lang="en">
<head>
{{template "meta_tags" "404, List Not Found"}}
{{template "user_style" .}}
</head>
<body>

View File

@@ -5,7 +5,9 @@
<title>{{.Title}}</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
{{template "user_style" .}}
<link id="stylesheet_layout" rel="stylesheet" type="text/css" href="/res/style/layout.css"/>
<link id="stylesheet_theme" rel="stylesheet" type="text/css" href="/theme.css"/>
<link rel="icon" sizes="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />

View File

@@ -7,7 +7,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
{{ template "opengraph" .OGData }}
{{ template "user_style" . }}
<link id="stylesheet_layout" rel="stylesheet" type="text/css" href="/res/style/layout.css"/>
<link id="stylesheet_layout" rel="stylesheet" type="text/css" href="{{.Other.ThemeURI}}"/>
<link rel="icon" sizes="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />

View File

@@ -5,7 +5,9 @@
<title>{{.Title}}</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
{{template "user_style" .}}
<link id="stylesheet_layout" rel="stylesheet" type="text/css" href="/res/style/layout.css"/>
<link id="stylesheet_theme" rel="stylesheet" type="text/css" href="/theme.css"/>
<link rel="icon" sizes="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />

View File

@@ -103,7 +103,6 @@
<html lang="en">
<head>
{{template "meta_tags" .Title}}
{{template "user_style" .}}
<script>var apiEndpoint = '{{.APIEndpoint}}';</script>
</head>

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" .Title}}
{{template "user_style" .}}
</head>
<body>

View File

@@ -3,6 +3,10 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="theme-color" content="#220735" />
<link id="stylesheet_layout" rel="stylesheet" type="text/css" href="/res/style/layout.css"/>
<link id="stylesheet_theme" rel="stylesheet" type="text/css" href="/theme.css"/>
<link rel="icon" sizes="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />
<link rel="icon" sizes="152x152" href="/res/img/pixeldrain_152.png" />

View File

@@ -1,6 +0,0 @@
{{define "user_style"}}
<style>
{{.UserStyle}}
{{template "layout.css" .}}
</style>
{{end}}

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Upload History"}}
{{template "user_style" .}}
</head>
<body>
{{template "page_top" .}}
@@ -23,7 +22,93 @@
<script>
let apiEndpoint = '{{.APIEndpoint}}';
{{template `history.js`}}
function renderFileButton(apiURL, id, title, subtitle) {
let btn = document.createElement("a")
btn.classList = "file_button"
btn.href = "/u/" + id
btn.target = "_blank"
let thumbnail = document.createElement("img")
thumbnail.src = apiURL + "/file/" + id + "/thumbnail?width=80&height=80"
thumbnail.alt = title
let titleSpan = document.createElement("span")
titleSpan.classList = "file_button_title"
titleSpan.innerText = title
let br = document.createElement("br")
let subtitleSpan = document.createElement("span")
subtitleSpan.classList = "file_button_subtitle"
subtitleSpan.innerText = subtitle
btn.appendChild(thumbnail)
btn.appendChild(titleSpan)
btn.appendChild(br)
btn.appendChild(subtitleSpan)
return btn
}
function getCookie(name) {
var result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie)
return result ? result[1] : null
}
function printDate(date, hours, minutes, seconds) {
let dateStr = date.getFullYear()
+ "-" + ("00" + (date.getMonth() + 1)).slice(-2)
+ "-" + ("00" + date.getDate()).slice(-2)
if (hours) { dateStr += " " + ("00" + date.getHours()).slice(-2) }
if (minutes) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
if (seconds) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
return dateStr
}
// Get the uploads from localstorage
let uploadsStr = localStorage.getItem("uploaded_files")
if (uploadsStr === null) { uploadsStr = "" }
let uploads = Array()
if (uploadsStr != "") {
// Strip the trailing comma
uploads = uploadsStr.slice(0, -1).split(",")
}
// Get the uploads from a cookie
uploadsStr = getCookie("pduploads")
if (uploadsStr === null) { uploadsStr = "" }
if (uploadsStr != "") {
uploadsStr = uploadsStr.slice(0, -1) // Strip the trailing dot
uploads.push(uploadsStr.split(".").reverse())
}
// Render all the items
function getHistoryItem() {
let item = uploads.shift()
if (item === undefined || item === "") { return }
fetch(
apiEndpoint + "/file/" + item + "/info"
).then(resp => {
if (!resp.ok) {
return Promise.reject()
}
return resp.json()
}).then(resp => {
document.getElementById("uploaded_files").appendChild(
renderFileButton(
apiEndpoint,
resp.id,
resp.name,
printDate(new Date(resp.date_upload), true, true, true),
)
)
getHistoryItem()
}).catch(err => {
console.log("Fetch failed: " + err)
getHistoryItem()
})
}
getHistoryItem()
</script>
{{template "analytics"}}
</body>

View File

@@ -3,7 +3,7 @@
<html lang="en">
<head>
{{template "meta_tags" "Free file sharing service"}}
{{template "user_style" .}}
<style>
/* Override the default background with something spectacular */
header, footer, .checkers {

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Maintenance"}}
{{template "user_style" .}}
</head>
<body>

View File

@@ -3,7 +3,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Text upload"}}
{{template "user_style" .}}
<script>
window.api_endpoint = '{{.APIEndpoint}}';

View File

@@ -2,7 +2,7 @@
<html lang="en">
<head>
{{template "meta_tags" "Buckets"}}
{{template "user_style" .}}
<script>window.api_endpoint = '{{.APIEndpoint}}';</script>
<link rel='stylesheet' href='/res/svelte/user_buckets.css?v{{.CacheID}}'>
<script defer src='/res/svelte/user_buckets.js?v{{.CacheID}}'></script>

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "File Manager"}}
{{template "user_style" .}}
<script>
window.api_endpoint = '{{.APIEndpoint}}';

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" .User.Username }}
{{template "user_style" . }}
<script>
window.api_endpoint = '{{.APIEndpoint}}';

View File

@@ -2,7 +2,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Logging out..."}}
{{template "user_style" .}}
</head>
<body>
{{template "page_top" .}}

View File

@@ -3,7 +3,6 @@
<html lang="en">
<head>
{{template "meta_tags" "Free file sharing service"}}
{{template "user_style" .}}
</head>
<body>
{{template "page_top" .}}

View File

@@ -311,7 +311,12 @@ const keyboard_event = evt => {
if (evt.ctrlKey || evt.altKey || evt.metaKey) {
return // prevent custom shortcuts from interfering with system shortcuts
}
if (document.activeElement.type && document.activeElement.type === "text") {
if (
document.activeElement.type && (
document.activeElement.type === "text" ||
document.activeElement.type === "textarea"
)
) {
return // Prevent shortcuts from interfering with input fields
}
@@ -685,8 +690,8 @@ const keyboard_event = evt => {
}
.file_preview {
position: absolute;
left: 0;
right: 0;
left: 4px;
right: 4px;
top: 0;
bottom: 0;
display: block;

View File

@@ -65,7 +65,7 @@ onMount(() => {
<p>
<strong>
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12">
<a href="https://www.patreon.com/join/pixeldrain" target="_blank" class="button button_highlight">
<i class="icon">bolt</i> Support Pixeldrain on Patreon
</a>
to disable the transfer limit

View File

@@ -89,7 +89,7 @@ onMount(async () => {
<button on:click={() => {dispatch("download")}}>
<i class="icon">download</i> Download
</button>
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12" target="_blank" class="button button_highlight">
<a href="https://www.patreon.com/join/pixeldrain" target="_blank" class="button button_highlight">
<i class="icon">bolt</i> Support Pixeldrain on Patreon
</a>
</div>

View File

@@ -55,7 +55,7 @@ onMount(async () => {
{formatDuration((file.size/file.download_speed_limit)*1000)}
</li>
<li>
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12" target="_blank" class="button button_highlight">
<a href="https://www.patreon.com/join/pixeldrain" target="_blank" class="button button_highlight">
<i class="icon">bolt</i> Support Pixeldrain on Patreon
</a>
and earn my eternal gratitude

View File

@@ -156,15 +156,15 @@ const fullscreen = () => {
still download the video and watch it locally on your computer without
an account.
<br/>
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12" target="_blank" class="button button_highlight">
<i class="icon">bolt</i> Get Pixeldrain Pro
</a>
<button on:click={download}>
<i class="icon">download</i> Download
</button>
<a href="/register" class="button">
<i class="icon">how_to_reg</i> Sign up
</a>
<a href="https://www.patreon.com/join/pixeldrain" target="_blank" class="button button_highlight">
<i class="icon">bolt</i> Get Pixeldrain Pro
</a>
</TextBlock>
<br/><br/>

View File

@@ -53,7 +53,7 @@ onMount(() => {
Data transfer limit
</div>
<div class="feat_normal">
5 GB data transfer per 24 hours. When this threshold is reached
10 GB data transfer per 24 hours. When this threshold is reached
your download speed will be reduced
</div>
<div class="feat_pro">

View File

@@ -264,9 +264,9 @@ onDestroy(() => {
{/if}
{#if transfer_cap === -1}
Paid transfers in the last 30 days: {formatDataVolume(transfer_used, 3)}<br/>
Premium transfers in the last 30 days: {formatDataVolume(transfer_used, 3)}<br/>
{:else}
Paid transfers:
Premium transfers:
{formatDataVolume(transfer_used, 3)}
out of
{formatDataVolume(transfer_cap, 3)}

View File

@@ -2,6 +2,7 @@ package webcontroller
import (
"fmt"
"html/template"
"net/http"
"strings"
"time"
@@ -24,12 +25,35 @@ func browserCompat(ua string) bool {
}
type fileViewerData struct {
Type string `json:"type"` // file or list
APIResponse interface{} `json:"api_response"`
CaptchaKey string `json:"captcha_key"`
ViewToken string `json:"view_token"`
Embedded bool `json:"embedded"`
UserAdsEnabled bool `json:"user_ads_enabled"`
Type string `json:"type"` // file or list
APIResponse interface{} `json:"api_response"`
CaptchaKey string `json:"captcha_key"`
ViewToken string `json:"view_token"`
Embedded bool `json:"embedded"`
UserAdsEnabled bool `json:"user_ads_enabled"`
ThemeURI template.URL `json:"theme_uri"`
}
func (vd *fileViewerData) themeOverride(r *http.Request, files []pixelapi.ListFile) {
vd.ThemeURI = "/theme.css"
var theme = r.URL.Query().Get("style")
var hue = r.URL.Query().Get("hue")
if files[0].Branding != nil {
if theme == "" {
theme = files[0].Branding["theme"]
}
if hue == "" {
hue = files[0].Branding["hue"]
}
}
if theme != "" {
vd.ThemeURI += template.URL("?style=" + theme)
if hue != "" {
vd.ThemeURI += template.URL("&hue=" + hue)
}
}
}
// ServeFileViewer controller for GET /u/:id
@@ -95,10 +119,9 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
vd.Embedded = true
}
vd.themeOverride(r, files)
templateData.Other = vd
fileStyleOverride(templateData, files)
for _, file := range files {
if file.AbuseType != "" {
w.WriteHeader(http.StatusUnavailableForLegalReasons)
@@ -157,9 +180,9 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
if _, ok := r.URL.Query()["embed"]; ok {
vd.Embedded = true
}
templateData.Other = vd
fileStyleOverride(templateData, list.Files)
vd.themeOverride(r, list.Files)
templateData.Other = vd
for _, file := range list.Files {
if file.AbuseType != "" {
@@ -179,16 +202,6 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
}
}
func fileStyleOverride(td *TemplateData, files []pixelapi.ListFile) {
if len(files) == 0 {
return
}
if files[0].Branding != nil && files[0].Branding["theme"] != "" {
td.setStyle(userStyle(files[0].Branding["theme"]))
}
}
// ServeFileViewerDemo is a dummy API response that responds with info about a
// non-existent demo file. This is required by the a-ads ad network to allow for
// automatic checking of the presence of the ad unit on this page.

View File

@@ -1,17 +1,29 @@
package webcontroller
import (
"bytes"
"fmt"
"html/template"
"math/rand"
"net/http"
"strconv"
"time"
"github.com/julienschmidt/httprouter"
)
func (wc *WebController) themeHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
w.Header().Set("Content-Type", "text/css")
w.Write([]byte(userStyleFromRequest(r)))
}
func userStyleFromRequest(r *http.Request) (s template.CSS) {
// Get the chosen style from the URL
var style = r.URL.Query().Get("style")
var hue = -1
if hueStr := r.URL.Query().Get("hue"); hueStr != "" {
hue, _ = strconv.Atoi(hueStr)
}
// If the URL style was empty use the cookie value
if style == "" {
@@ -19,110 +31,175 @@ func userStyleFromRequest(r *http.Request) (s template.CSS) {
style = cookie.Value
}
}
if hue == -1 {
if cookie, err := r.Cookie("hue"); err == nil {
hue, _ = strconv.Atoi(cookie.Value)
}
}
return userStyle(style)
return userStyle(style, hue)
}
func userStyle(style string) template.CSS {
func userStyle(style string, hue int) template.CSS {
var (
def styleSheet
light styleSheet
hasLight bool
)
switch style {
case "nord":
return template.CSS(nordDarkStyle.withLight(nordLightStyle))
case "nord_dark":
return template.CSS(nordDarkStyle.String())
case "nord_light", "snowstorm":
return template.CSS(nordLightStyle.String())
case "solarized":
return template.CSS(solarizedDarkStyle.withLight(solarizedLightStyle))
case "solarized_dark":
return template.CSS(solarizedDarkStyle.String())
case "solarized_light":
return template.CSS(solarizedLightStyle.String())
case "classic":
return template.CSS(classicStyle.String())
case "purple_drain":
return template.CSS(defaultPixeldrainStyle.String())
case "maroon":
return template.CSS(maroonStyle.String())
case "hacker":
return template.CSS(hackerStyle.String())
case "canta":
return template.CSS(cantaPixeldrainStyle.String())
case "skeuos":
return template.CSS(skeuosPixeldrainStyle.String())
case "sweet":
return template.CSS(sweetPixeldrainStyle.String())
case "adwaita":
return template.CSS(adwaitaDarkStyle.withLight(adwaitaLightStyle))
default:
return template.CSS(nordDarkStyle.withLight(nordLightStyle))
fallthrough
case "nord":
def = nordDarkStyle
light = nordLightStyle
hasLight = true
case "nord_dark":
def = nordDarkStyle
case "nord_light", "snowstorm":
def = nordLightStyle
case "solarized":
def = solarizedDarkStyle
light = solarizedLightStyle
hasLight = true
case "solarized_dark":
def = solarizedDarkStyle
case "solarized_light":
def = solarizedLightStyle
case "classic":
def = classicStyle
hue = -1 // Does not support custom hues
case "purple_drain":
def = purpleDrainStyle
hue = -1 // Does not support custom hues
case "maroon":
def = maroonStyle
case "hacker":
def = hackerStyle
hue = -1 // Does not support custom hues
case "canta":
def = cantaPixeldrainStyle
case "skeuos":
def = skeuosPixeldrainStyle
case "sweet":
def = sweetPixeldrainStyle
case "adwaita":
def = adwaitaDarkStyle
light = adwaitaLightStyle
hasLight = true
}
if hue >= 0 && hue <= 360 {
def = def.withHue(hue)
light = light.withHue(hue)
}
if hasLight {
return template.CSS(def.withLight(light))
} else {
return template.CSS(def.String())
}
}
type styleSheet struct {
Link hsl // Based on Highlight if undefined
Input Color
InputHover Color
InputText Color
InputDisabledText Color
HighlightBackground Color
Highlight hsl // Links, highlighted buttons, list navigation
HighlightText hsl // Text on buttons
Danger hsl
ScrollbarForeground Color // Based on Highlight if undefined
ScrollbarHover Color // Based on ScrollbarForeground if undefined
Link HSL // Based on Highlight if undefined
Input CSS
InputHover CSS
InputText CSS
InputDisabledText CSS
HighlightBackground CSS
Highlight HSL // Links, highlighted buttons, list navigation
HighlightText HSL // Text on buttons
Danger HSL
ScrollbarForeground CSS // Based on Highlight if undefined
ScrollbarHover CSS // Based on ScrollbarForeground if undefined
BackgroundColor hsl
Background Color
BackgroundText hsl
BackgroundPattern Color
ParallaxSlider Color
Navigation Color
BodyColor hsl
BodyBackground Color
BodyText hsl
Separator Color
CardColor hsl
CardText hsl
BackgroundColor HSL
Background CSS
BackgroundText HSL
BackgroundPattern CSS
ParallaxSlider CSS
Navigation CSS
BodyColor HSL
BodyBackground CSS
BodyText HSL
Separator CSS
CardColor HSL
CardText HSL
// Colors to use in graphs
Chart1 hsl
Chart2 hsl
Chart3 hsl
Chart1 HSL
Chart2 HSL
Chart3 HSL
Shadow hsl
Shadow HSL
}
func (s styleSheet) withDefaults() styleSheet {
// Set default colors
var noColor = hsl{0, 0, 0}
var defaultHSL = func(color *hsl, def hsl) {
if *color == noColor {
*color = def
var noColor = HSL{0, 0, 0}
var defaultHSL = func(target *HSL, def HSL) {
if *target == noColor {
*target = def
}
}
var defaultColor = func(color *Color, def Color) {
if *color == nil {
*color = def
var defaultCSS = func(target *CSS, def CSS) {
if *target == nil {
*target = def
}
}
defaultHSL(&s.Link, s.Highlight.Add(0, 0, -.05))
defaultColor(&s.ScrollbarForeground, s.Input)
defaultColor(&s.ScrollbarHover, s.Highlight)
defaultCSS(&s.ScrollbarForeground, s.Input)
defaultCSS(&s.ScrollbarHover, s.Highlight)
defaultHSL(&s.Chart1, s.Highlight)
defaultHSL(&s.Chart2, s.Chart1.Add(120, 0, 0))
defaultHSL(&s.Chart3, s.Chart2.Add(120, 0, 0))
defaultColor(&s.HighlightBackground, s.Highlight)
defaultColor(&s.Background, s.BackgroundColor)
defaultColor(&s.BackgroundPattern, s.BackgroundColor)
defaultColor(&s.ParallaxSlider, s.BackgroundColor)
defaultColor(&s.Navigation, NoColor)
defaultColor(&s.BodyBackground, s.BodyColor)
defaultCSS(&s.HighlightBackground, s.Highlight)
defaultCSS(&s.Background, s.BackgroundColor)
defaultCSS(&s.BackgroundPattern, s.BackgroundColor)
defaultCSS(&s.ParallaxSlider, s.BackgroundColor)
defaultCSS(&s.Navigation, RawCSS("none"))
defaultCSS(&s.BodyBackground, s.BodyColor)
defaultHSL(&s.BackgroundText, s.BodyText)
defaultColor(&s.Separator, s.BodyColor.Add(0, 0, .05))
defaultCSS(&s.Separator, s.BodyColor.Add(0, 0, .05))
return s
}
func (s styleSheet) withHue(hue int) styleSheet {
s = s.withDefaults()
var setHue = func(c CSS) CSS {
if hsl, ok := c.(HSL); ok {
hsl.Hue = hue
return hsl
} else {
return c
}
}
s.Input = setHue(s.Input)
s.InputHover = setHue(s.InputHover)
s.InputText = setHue(s.InputText)
s.InputDisabledText = setHue(s.InputDisabledText)
s.ScrollbarForeground = setHue(s.ScrollbarForeground)
s.ScrollbarHover = setHue(s.ScrollbarHover)
s.BackgroundColor.Hue = hue
s.Background = setHue(s.Background)
s.BackgroundText.Hue = hue
s.BackgroundPattern = setHue(s.BackgroundPattern)
s.ParallaxSlider = setHue(s.ParallaxSlider)
s.Navigation = setHue(s.Navigation)
s.BodyColor.Hue = hue
s.BodyBackground = setHue(s.BodyBackground)
s.BodyText.Hue = hue
s.Separator = setHue(s.Separator)
s.CardColor.Hue = hue
s.CardText.Hue = hue
s.Shadow.Hue = hue
return s
}
func (s styleSheet) String() string {
s = s.withDefaults()
@@ -144,6 +221,7 @@ func (s styleSheet) String() string {
--background_color: %s;
--background: %s;
--background_text_color: %s;
--background_pattern: url("%s");
--background_pattern_color: %s;
--parallax_slider_color: %s;
--navigation_background: %s;
@@ -175,6 +253,7 @@ func (s styleSheet) String() string {
s.BackgroundColor.CSS(),
s.Background.CSS(),
s.BackgroundText.CSS(),
BackgroundTiles(),
s.BackgroundPattern.CSS(),
s.ParallaxSlider.CSS(),
s.Navigation.CSS(),
@@ -203,7 +282,7 @@ func (dark styleSheet) withLight(light styleSheet) string {
)
}
func BackgroundTiles(tpl *template.Template) template.URL {
func BackgroundTiles() template.URL {
var (
now = time.Now()
month = now.Month()
@@ -226,262 +305,264 @@ func BackgroundTiles(tpl *template.Template) template.URL {
file = fmt.Sprintf("checker%d", now.UnixNano()%18)
}
var buf = bytes.Buffer{}
if err := tpl.ExecuteTemplate(&buf, file+"_transparent.png", nil); err != nil {
panic(err)
}
return template.URL(buf.String())
return template.URL("/res/img/background_patterns/" + file + "_transparent.png")
// var buf = bytes.Buffer{}
// if err := tpl.ExecuteTemplate(&buf, file+"_transparent.png", nil); err != nil {
// panic(err)
// }
// return template.URL(buf.String())
}
// Following are all the available styles
var defaultPixeldrainStyle = styleSheet{
Input: hsl{266, .85, .24},
InputHover: hsl{266, .85, .28},
InputText: hsl{0, 0, .9},
InputDisabledText: hsl{266, .85, .4},
HighlightBackground: NewGradient(150, hsl{150, .84, .39}, hsl{85, .85, .35}),
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},
var purpleDrainStyle = styleSheet{
Input: HSL{266, .85, .24},
InputHover: HSL{266, .85, .28},
InputText: HSL{0, 0, .9},
InputDisabledText: HSL{266, .85, .4},
HighlightBackground: NewGradient(150, HSL{150, .84, .39}, HSL{85, .85, .35}),
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},
BackgroundColor: hsl{273, .93, .12},
Background: NewGradient(120, hsl{250, .9, .14}, hsl{300, .9, .10}),
BackgroundPattern: NoColor,
ParallaxSlider: hsl{275, .8, .1},
BackgroundColor: HSL{273, .93, .12},
Background: NewGradient(120, HSL{250, .9, .14}, HSL{300, .9, .10}),
BackgroundPattern: RawCSS("none"),
ParallaxSlider: HSL{275, .8, .1},
Navigation: RGBA{0, 0, 0, 0.1},
BodyColor: hsl{274, .9, .14},
BodyBackground: NoColor,
BodyText: hsl{0, 0, .8},
CardColor: hsl{275, .8, .18},
BodyColor: HSL{274, .9, .14},
BodyBackground: RawCSS("none"),
BodyText: HSL{0, 0, .8},
CardColor: HSL{275, .8, .18},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var classicStyle = styleSheet{
Input: hsl{0, 0, .18},
InputHover: hsl{0, 0, .22},
InputText: hsl{0, 0, .9},
InputDisabledText: hsl{0, 0, .4},
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},
Input: HSL{0, 0, .18},
InputHover: HSL{0, 0, .22},
InputText: HSL{0, 0, .9},
InputDisabledText: HSL{0, 0, .4},
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},
BackgroundColor: hsl{0, 0, .08},
BodyColor: hsl{0, 0, .12},
BodyText: hsl{0, 0, .8},
CardColor: hsl{0, 0, .16},
BackgroundColor: HSL{0, 0, .08},
BodyColor: HSL{0, 0, .12},
BodyText: HSL{0, 0, .8},
CardColor: HSL{0, 0, .16},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var maroonStyle = styleSheet{
Input: hsl{0, .8, .20}, // hsl(0, 87%, 40%)
InputHover: hsl{0, .8, .24},
InputText: hsl{0, 0, 1},
InputDisabledText: hsl{0, 0, .5},
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},
Input: HSL{0, .8, .20}, // hsl(0, 87%, 40%)
InputHover: HSL{0, .8, .24},
InputText: HSL{0, 0, 1},
InputDisabledText: HSL{0, 0, .5},
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},
BackgroundColor: hsl{0, .7, .05},
BodyColor: hsl{0, .8, .08}, // hsl{0, .8, .15},
BodyText: hsl{0, 0, .8},
CardColor: hsl{0, .9, .14},
BackgroundColor: HSL{0, .7, .05},
BodyColor: HSL{0, .8, .08}, // HSL{0, .8, .15},
BodyText: HSL{0, 0, .8},
CardColor: HSL{0, .9, .14},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var hackerStyle = styleSheet{
Input: hsl{0, 0, .1},
InputHover: hsl{0, 0, .14},
InputText: hsl{0, 0, 1},
InputDisabledText: hsl{0, 0, .5},
Highlight: hsl{120, .8, .5},
HighlightText: hsl{0, 0, 0},
Danger: hsl{0, 1, .4},
ScrollbarForeground: hsl{120, .5, .25},
ScrollbarHover: hsl{120, .5, .35},
Input: HSL{0, 0, .1},
InputHover: HSL{0, 0, .14},
InputText: HSL{0, 0, 1},
InputDisabledText: HSL{0, 0, .5},
Highlight: HSL{120, .8, .5},
HighlightText: HSL{0, 0, 0},
Danger: HSL{0, 1, .4},
ScrollbarForeground: HSL{120, .5, .25},
ScrollbarHover: HSL{120, .5, .35},
BackgroundColor: hsl{0, 0, 0},
BodyColor: hsl{0, 0, .03},
BodyText: hsl{0, 0, .8},
CardColor: hsl{120, .4, .05},
BackgroundColor: HSL{0, 0, 0},
BodyColor: HSL{0, 0, .03},
BodyText: HSL{0, 0, .8},
CardColor: HSL{120, .4, .05},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var cantaPixeldrainStyle = styleSheet{
Input: hsl{167, .06, .30}, // hsl(167, 6%, 30%)
InputHover: hsl{167, .06, .34}, // hsl(167, 6%, 30%)
InputText: hsl{0, 0, 1},
InputDisabledText: hsl{0, 0, .5},
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},
Input: HSL{167, .06, .30}, // hsl(167, 6%, 30%)
InputHover: HSL{167, .06, .34}, // hsl(167, 6%, 30%)
InputText: HSL{0, 0, 1},
InputDisabledText: HSL{0, 0, .5},
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},
BackgroundColor: hsl{180, .04, .16},
BodyColor: hsl{168, .05, .21},
BodyText: hsl{0, 0, .8},
CardColor: hsl{170, .05, .26},
BackgroundColor: HSL{180, .04, .16},
BodyColor: HSL{168, .05, .21},
BodyText: HSL{0, 0, .8},
CardColor: HSL{170, .05, .26},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var skeuosPixeldrainStyle = styleSheet{
Input: hsl{226, .15, .23}, //hsl(226, 15%, 23%)
InputHover: hsl{226, .15, .27},
InputText: hsl{60, .06, .93},
InputDisabledText: hsl{0, 0, .5},
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},
Input: HSL{226, .15, .23}, //hsl(226, 15%, 23%)
InputHover: HSL{226, .15, .27},
InputText: HSL{60, .06, .93},
InputDisabledText: HSL{0, 0, .5},
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},
BackgroundColor: hsl{232, .14, .11}, //hsl(232, 14%, 11%)
BodyColor: hsl{229, .14, .16}, // hsl(229, 14%, 16%)
BodyText: hsl{60, .06, .93}, // hsl(60, 6%, 93%)
CardColor: hsl{225, .14, .17}, // hsl(225, 14%, 17%)
BackgroundColor: HSL{232, .14, .11}, //hsl(232, 14%, 11%)
BodyColor: HSL{229, .14, .16}, // hsl(229, 14%, 16%)
BodyText: HSL{60, .06, .93}, // hsl(60, 6%, 93%)
CardColor: HSL{225, .14, .17}, // hsl(225, 14%, 17%)
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var nordDarkStyle = styleSheet{
Input: hsl{220, .16, .36}, // nord3
InputHover: hsl{220, .16, .40},
InputText: hsl{218, .27, .92}, // nord5 hsl(218, 27%, 92%)
InputDisabledText: hsl{220, .16, .22}, // nord0 hsl(220, 16%, 22%)
Highlight: hsl{92, .28, .65}, // nord14 hsl(92, 28%, 65%)
HighlightText: hsl{220, .16, .22}, // nord0
Danger: hsl{354, .42, .56}, // nord11 hsl(354, 42%, 56%)
ScrollbarForeground: hsl{179, .25, .65}, // nord7 hsl(179, 25%, 65%)
ScrollbarHover: hsl{193, .43, .67}, // nord8 hsl(193, 43%, 67%)
Input: HSL{220, .16, .36}, // nord3
InputHover: HSL{220, .16, .40},
InputText: HSL{218, .27, .92}, // nord5 hsl(218, 27%, 92%)
InputDisabledText: HSL{220, .16, .22}, // nord0 hsl(220, 16%, 22%)
Highlight: HSL{92, .28, .65}, // nord14 hsl(92, 28%, 65%)
HighlightText: HSL{220, .16, .22}, // nord0
Danger: HSL{354, .42, .56}, // nord11 hsl(354, 42%, 56%)
ScrollbarForeground: HSL{179, .25, .65}, // nord7 hsl(179, 25%, 65%)
ScrollbarHover: HSL{193, .43, .67}, // nord8 hsl(193, 43%, 67%)
BackgroundColor: hsl{220, .16, .22}, // nord0
BodyColor: hsl{222, .16, .28}, // nord1
BodyText: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
CardColor: hsl{220, .17, .32}, // nord2
BackgroundColor: HSL{220, .16, .22}, // nord0
BodyColor: HSL{222, .16, .28}, // nord1
BodyText: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
CardColor: HSL{220, .17, .32}, // nord2
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var nordLightStyle = styleSheet{
Link: hsl{92, .40, .32},
Input: hsl{218, .27, .94}, // nord6 hsl(218, 27%, 94%)
InputHover: hsl{218, .27, .98},
InputText: hsl{222, .16, .28}, // nord1 hsl(222, 16%, 28%)
InputDisabledText: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
Highlight: hsl{92, .28, .65}, // nord14 hsl(92, 28%, 65%)
HighlightText: hsl{222, .16, .28}, // nord3 hsl(220, 16%, 36%)
Danger: hsl{354, .42, .56}, // nord11 hsl(354, 42%, 56%)
ScrollbarForeground: hsl{179, .25, .65}, // nord7 hsl(179, 25%, 65%)
ScrollbarHover: hsl{193, .43, .67}, // nord8 hsl(193, 43%, 67%)
Link: HSL{92, .40, .32},
Input: HSL{218, .27, .94}, // nord6 hsl(218, 27%, 94%)
InputHover: HSL{218, .27, .98},
InputText: HSL{222, .16, .28}, // nord1 hsl(222, 16%, 28%)
InputDisabledText: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
Highlight: HSL{92, .28, .65}, // nord14 hsl(92, 28%, 65%)
HighlightText: HSL{222, .16, .28}, // nord3 hsl(220, 16%, 36%)
Danger: HSL{354, .42, .56}, // nord11 hsl(354, 42%, 56%)
ScrollbarForeground: HSL{179, .25, .65}, // nord7 hsl(179, 25%, 65%)
ScrollbarHover: HSL{193, .43, .67}, // nord8 hsl(193, 43%, 67%)
BackgroundColor: hsl{220, .16, .36}, // nord3 hsl(220, 16%, 36%)
BackgroundText: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
ParallaxSlider: hsl{220, .16, .22}, // nord0 hsl(220, 16%, 22%)
BodyColor: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
BodyText: hsl{220, .17, .32}, // nord2 hsl(220, 17%, 32%)
BackgroundPattern: hsl{219, .28, .88}, // hsl(219, 28%, 88%)
CardColor: hsl{218, .27, .92}, // nord5 hsl(218, 27%, 92%)
BackgroundColor: HSL{220, .16, .36}, // nord3 hsl(220, 16%, 36%)
BackgroundText: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
ParallaxSlider: HSL{220, .16, .22}, // nord0 hsl(220, 16%, 22%)
BodyColor: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
BodyText: HSL{220, .17, .32}, // nord2 hsl(220, 17%, 32%)
BackgroundPattern: HSL{219, .28, .88}, // hsl(219, 28%, 88%)
CardColor: HSL{218, .27, .92}, // nord5 hsl(218, 27%, 92%)
Shadow: hsl{220, .16, .36},
Shadow: HSL{220, .16, .36},
}
var sweetPixeldrainStyle = styleSheet{
Input: hsl{229, .25, .18}, // hsl(229, 25%, 14%)
InputHover: hsl{229, .25, .22}, // hsl(229, 25%, 14%)
InputText: hsl{223, .13, .79},
InputDisabledText: hsl{0, 0, .5},
Highlight: hsl{296, .88, .44},
HighlightText: hsl{0, 0, 0},
Danger: hsl{356, 1, .64}, // hsl(356, 100%, 64%)
Input: HSL{229, .25, .18}, // hsl(229, 25%, 14%)
InputHover: HSL{229, .25, .22}, // hsl(229, 25%, 14%)
InputText: HSL{223, .13, .79},
InputDisabledText: HSL{0, 0, .5},
Highlight: HSL{296, .88, .44},
HighlightText: HSL{0, 0, 0},
Danger: HSL{356, 1, .64}, // hsl(356, 100%, 64%)
BackgroundColor: hsl{225, .25, .06}, // hsl(225, 25%, 6%)
BodyColor: hsl{228, .25, .12}, // hsl(228, 25%, 12%)
BodyText: hsl{223, .13, .79}, // hsl(223, 13%, 79%)
BackgroundColor: HSL{225, .25, .06}, // hsl(225, 25%, 6%)
BodyColor: HSL{228, .25, .12}, // hsl(228, 25%, 12%)
BodyText: HSL{223, .13, .79}, // hsl(223, 13%, 79%)
Separator: RGBA{255, 255, 255, 0.05},
CardColor: hsl{229, .25, .14}, // hsl(229, 25%, 14%)
CardColor: HSL{229, .25, .14}, // hsl(229, 25%, 14%)
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var adwaitaDarkStyle = styleSheet{
Input: RGBA{255, 255, 255, .06},
InputHover: RGBA{255, 255, 255, .1},
InputText: hsl{0, 0, 1},
InputDisabledText: hsl{0, 0, .5},
Highlight: hsl{152, .62, .39}, // hsl(152, 62%, 39%)
HighlightText: hsl{0, 0, 0},
Danger: hsl{9, 1, .69}, // hsl(9, 100%, 69%)
InputText: HSL{0, 0, 1},
InputDisabledText: HSL{0, 0, .5},
Highlight: HSL{152, .62, .39}, // hsl(152, 62%, 39%)
HighlightText: HSL{0, 0, 0},
Danger: HSL{9, 1, .69}, // hsl(9, 100%, 69%)
BackgroundColor: hsl{0, 0, .19},
BodyColor: hsl{0, 0, .14},
BodyText: hsl{0, 0, 1},
BackgroundColor: HSL{0, 0, .19},
BodyColor: HSL{0, 0, .14},
BodyText: HSL{0, 0, 1},
Separator: RGBA{255, 255, 255, 0.04},
CardColor: hsl{0, 0, .08},
CardColor: HSL{0, 0, .08},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var adwaitaLightStyle = styleSheet{
Input: RGBA{0, 0, 0, .06},
InputHover: RGBA{0, 0, 0, .1},
InputText: hsl{0, 0, .2},
InputDisabledText: hsl{0, 0, .7},
Highlight: hsl{152, .62, .47}, // hsl(152, 62%, 47%)
HighlightText: hsl{0, 0, 1},
Danger: hsl{356, .75, .43}, // hsl(356, 75%, 43%)
InputText: HSL{0, 0, .2},
InputDisabledText: HSL{0, 0, .7},
Highlight: HSL{152, .62, .47}, // hsl(152, 62%, 47%)
HighlightText: HSL{0, 0, 1},
Danger: HSL{356, .75, .43}, // hsl(356, 75%, 43%)
BackgroundColor: hsl{0, 0, .92},
BodyColor: hsl{0, 0, .98},
BodyText: hsl{0, 0, .2},
CardColor: hsl{0, 0, 1},
BackgroundColor: HSL{0, 0, .92},
BodyColor: HSL{0, 0, .98},
BodyText: HSL{0, 0, .2},
CardColor: HSL{0, 0, 1},
Shadow: hsl{0, 0, 0.36},
Shadow: HSL{0, 0, 0.36},
}
var solarizedDarkStyle = styleSheet{
Input: hsl{192, .81, .18}, // hsl(194, 14%, 40%)
InputHover: hsl{192, .81, .22}, // hsl(196, 13%, 45%)
InputText: hsl{180, .07, .80}, // hsl(44, 87%, 94%)
InputDisabledText: hsl{194, .14, .30}, // hsl(194, 14%, 40%)
Highlight: hsl{68, 1, .30}, // hsl(68, 100%, 30%)
HighlightText: hsl{192, .81, .14}, // hsl(192, 100%, 11%)
Danger: hsl{1, .71, .52}, // hsl(1, 71%, 52%)
Input: HSL{192, .81, .18}, // hsl(194, 14%, 40%)
InputHover: HSL{192, .81, .22}, // hsl(196, 13%, 45%)
InputText: HSL{180, .07, .80}, // hsl(44, 87%, 94%)
InputDisabledText: HSL{194, .14, .30}, // hsl(194, 14%, 40%)
Highlight: HSL{68, 1, .30}, // hsl(68, 100%, 30%)
HighlightText: HSL{192, .81, .14}, // hsl(192, 100%, 11%)
Danger: HSL{1, .71, .52}, // hsl(1, 71%, 52%)
BackgroundColor: hsl{192, 1, .11}, //hsl(192, 100%, 11%)
BodyColor: hsl{192, .81, .14}, // hsl(192, 81%, 14%)
BodyText: hsl{180, .07, .60}, // hsl(180, 7%, 60%)
BackgroundColor: HSL{192, 1, .11}, //hsl(192, 100%, 11%)
BodyColor: HSL{192, .81, .14}, // hsl(192, 81%, 14%)
BodyText: HSL{180, .07, .60}, // hsl(180, 7%, 60%)
Separator: RGBA{255, 255, 255, 0.05},
CardColor: hsl{192, .81, .16},
CardColor: HSL{192, .81, .16},
Shadow: hsl{0, 0, 0},
Shadow: HSL{0, 0, 0},
}
var solarizedLightStyle = styleSheet{
Input: hsl{46, .42, .84}, //hsl(180, 7%, 60%)
InputHover: hsl{46, .42, .88},
InputText: hsl{194, .14, .20}, // hsl(192, 81%, 14%)
InputDisabledText: hsl{194, .14, .80},
Highlight: hsl{68, 1, .30}, // hsl(68, 100%, 30%)
HighlightText: hsl{44, .87, .94},
Danger: hsl{1, .71, .52}, // hsl(1, 71%, 52%)
Input: HSL{46, .42, .84}, //hsl(180, 7%, 60%)
InputHover: HSL{46, .42, .88},
InputText: HSL{194, .14, .20}, // hsl(192, 81%, 14%)
InputDisabledText: HSL{194, .14, .80},
Highlight: HSL{68, 1, .30}, // hsl(68, 100%, 30%)
HighlightText: HSL{44, .87, .94},
Danger: HSL{1, .71, .52}, // hsl(1, 71%, 52%)
BackgroundColor: hsl{46, .42, .88}, // hsl(46, 42%, 88%)
BodyColor: hsl{44, .87, .94}, // hsl(44, 87%, 94%)
BodyText: hsl{194, .14, .40}, // hsl(194, 14%, 40%)
BackgroundColor: HSL{46, .42, .88}, // hsl(46, 42%, 88%)
BodyColor: HSL{44, .87, .94}, // hsl(44, 87%, 94%)
BodyText: HSL{194, .14, .40}, // hsl(194, 14%, 40%)
Separator: RGBA{0, 0, 0, 0.05},
CardColor: hsl{44, .87, .96},
CardColor: HSL{44, .87, .96},
Shadow: hsl{0, 0, 0.36},
Shadow: HSL{0, 0, 0.36},
}

View File

@@ -2,29 +2,38 @@ package webcontroller
import (
"fmt"
"math"
)
type Color interface {
CSS
HSL() HSL
RGB() RGB
}
type CSS interface {
CSS() string
}
// Raw CSS
type CSS string
type RawCSS string
func (c CSS) CSS() string { return string(c) }
const NoColor = CSS("none")
func (c RawCSS) CSS() string { return string(c) }
// HSL color
type hsl struct {
type HSL struct {
Hue int
Saturation float64
Lightness float64
}
func (orig hsl) RGB() string {
var _ Color = HSL{} // Confirm interface compliance
func (hsl HSL) CSS() string { return hsl.RGB().CSS() }
func (hsl HSL) HSL() HSL { return hsl }
func (hsl HSL) RGB() RGB {
var r, g, b, q, p float64
var h, s, l = float64(orig.Hue) / 360, orig.Saturation, orig.Lightness
var h, s, l = float64(hsl.Hue) / 360, hsl.Saturation, hsl.Lightness
if s == 0 {
r, g, b = l, l, l
@@ -58,19 +67,15 @@ func (orig hsl) RGB() string {
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))
}
func (orig hsl) CSS() string {
return "#" + orig.RGB()
return RGB{R: uint8(r * 255), G: uint8(g * 255), B: uint8(b * 255)}
}
// Add returns a NEW HSL struct, it doesn't modify the current one
func (h hsl) Add(hue int, saturation float64, lightness float64) hsl {
var new = hsl{
h.Hue + hue,
h.Saturation + saturation,
h.Lightness + lightness,
func (hsl HSL) Add(hue int, saturation float64, lightness float64) HSL {
var new = HSL{
hsl.Hue + hue,
hsl.Saturation + saturation,
hsl.Lightness + lightness,
}
// Hue bounds correction
if new.Hue < 0 {
@@ -94,21 +99,27 @@ func (h hsl) Add(hue int, saturation float64, lightness float64) hsl {
return new
}
func (h hsl) WithAlpha(alpha float64) HSLA {
return HSLA{h, alpha}
func (hsl HSL) WithAlpha(alpha float64) HSLA {
return HSLA{hsl.Hue, hsl.Saturation, hsl.Lightness, alpha}
}
type HSLA struct {
hsl
Alpha float64
Hue int
Saturation float64
Lightness float64
Alpha float64
}
var _ Color = HSLA{}
func (hsla HSLA) CSS() string {
return fmt.Sprintf(
"hsla(%d, %.2f%%, %.2f%%, %.2f)",
hsla.Hue, hsla.Saturation*100, hsla.Lightness*100, hsla.Alpha,
)
}
func (hsla HSLA) HSL() HSL { return HSL{hsla.Hue, hsla.Saturation, hsla.Lightness} }
func (hsla HSLA) RGB() RGB { return hsla.HSL().RGB() }
type RGB struct {
R uint8
@@ -116,9 +127,55 @@ type RGB struct {
B uint8
}
func (rgb RGB) CSS() string {
return fmt.Sprintf("#%02x%02x%02x", rgb.R, rgb.G, rgb.B)
var _ Color = RGB{}
func (rgb RGB) CSS() string { return fmt.Sprintf("#%02x%02x%02x", rgb.R, rgb.G, rgb.B) }
func (rgb RGB) HSL() HSL {
var r, g, b = float64(rgb.R), float64(rgb.G), float64(rgb.B)
var h, s, l float64
max := math.Max(math.Max(r, g), b)
min := math.Min(math.Min(r, g), b)
// Luminosity is the average of the max and min rgb color intensities.
l = (max + min) / 2
// saturation
delta := max - min
if delta == 0 {
// it's gray
return HSL{0, 0, l}
}
// it's not gray
if l < 0.5 {
s = delta / (max + min)
} else {
s = delta / (2 - max - min)
}
// hue
r2 := (((max - r) / 6) + (delta / 2)) / delta
g2 := (((max - g) / 6) + (delta / 2)) / delta
b2 := (((max - b) / 6) + (delta / 2)) / delta
switch {
case r == max:
h = b2 - g2
case g == max:
h = (1.0 / 3.0) + r2 - b2
case b == max:
h = (2.0 / 3.0) + g2 - r2
}
if h < 0 {
h += 1
} else if h > 1 {
h -= 1
}
return HSL{int(h), s, l}
}
func (rgb RGB) RGB() RGB { return rgb }
type RGBA struct {
R uint8
@@ -127,15 +184,22 @@ type RGBA struct {
A float64
}
var _ Color = RGBA{}
func (rgba RGBA) CSS() string {
return fmt.Sprintf("rgba(%d, %d, %d, %f)", rgba.R, rgba.G, rgba.B, rgba.A)
}
func (rgba RGBA) HSL() HSL { return rgba.RGB().HSL() }
func (rgba RGBA) RGB() RGB { return RGB{rgba.R, rgba.G, rgba.B} }
type Gradient struct {
Angle int
Colors []Color
}
var _ CSS = Gradient{}
func NewGradient(angle int, colors ...Color) Gradient {
return Gradient{angle, colors}
}

View File

@@ -21,15 +21,13 @@ import (
// TemplateData is a struct that every template expects when being rendered. In
// the field Other you can pass your own template-specific variables.
type TemplateData struct {
tpm *TemplateManager
Authenticated bool
User pixelapi.UserInfo
UserAgent string
UserStyle template.CSS
BackgroundPattern template.URL
APIEndpoint template.URL
PixelAPI pixelapi.PixelAPI
Hostname template.HTML
tpm *TemplateManager
Authenticated bool
User pixelapi.UserInfo
UserAgent string
APIEndpoint template.URL
PixelAPI pixelapi.PixelAPI
Hostname template.HTML
// Only used on file viewer page
Title string
@@ -45,11 +43,6 @@ type TemplateData struct {
Form Form
}
func (td *TemplateData) setStyle(style template.CSS) {
td.UserStyle = style
td.BackgroundPattern = BackgroundTiles(td.tpm.tpl)
}
func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) (t *TemplateData) {
t = &TemplateData{
tpm: wc.templates,
@@ -65,8 +58,6 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
URLQuery: r.URL.Query(),
}
t.setStyle(userStyleFromRequest(r))
// If the user is authenticated we'll indentify him and put the user info
// into the templatedata. This is used for putting the username in the menu
// and stuff like that
@@ -245,7 +236,7 @@ func (tm *TemplateManager) mul(a, b interface{}) float64 { return toFloat(a) * t
func (tm *TemplateManager) div(a, b interface{}) float64 { return toFloat(a) / toFloat(b) }
func (tm *TemplateManager) formatData(i interface{}) string {
return util.FormatData(int64(detectInt(i)))
return util.FormatData(detectInt(i))
}
func (tm *TemplateManager) formatSC(amt float64) string {
var fmtSize = func(n float64, u string) string {

View File

@@ -133,7 +133,7 @@ func New(
r.NotFound = http.HandlerFunc(wc.serveNotFound)
// Request method shorthands. These help keep the array of handlers aligned
const PST, GET, PUT, DEL = "POST", "GET", "PUT", "DELETE"
const PST, GET = "POST", "GET"
// Loop over the handlers and register all of them in the router
for _, h := range []struct {
@@ -217,6 +217,7 @@ func New(
// Misc
{GET, "misc/sharex/pixeldrain.com.sxcu", wc.serveShareXConfig},
{GET, "theme.css", wc.themeHandler},
} {
r.Handle(h.method, prefix+"/"+h.path, h.handler)
}