Theming changes
14
go.mod
@@ -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
@@ -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=
|
||||
|
Before Width: | Height: | Size: 906 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 220 KiB |
@@ -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>
|
||||
|
@@ -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()
|
Before Width: | Height: | Size: 92 B After Width: | Height: | Size: 92 B |
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 111 B |
Before Width: | Height: | Size: 132 B After Width: | Height: | Size: 132 B |
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
Before Width: | Height: | Size: 124 B After Width: | Height: | Size: 124 B |
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B |
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 128 B |
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 151 B |
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 366 B |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 455 B |
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
Before Width: | Height: | Size: 108 B After Width: | Height: | Size: 108 B |
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 133 B After Width: | Height: | Size: 133 B |
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 338 B |
Before Width: | Height: | Size: 116 B After Width: | Height: | Size: 116 B |
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 127 B After Width: | Height: | Size: 127 B |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 122 B After Width: | Height: | Size: 122 B |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 120 B |
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 322 B |
Before Width: | Height: | Size: 138 B After Width: | Height: | Size: 138 B |
Before Width: | Height: | Size: 343 B After Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 646 B After Width: | Height: | Size: 646 B |
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 379 B |
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 195 B |
Before Width: | Height: | Size: 399 B After Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 396 B After Width: | Height: | Size: 396 B |
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 633 B |
Before Width: | Height: | Size: 959 B After Width: | Height: | Size: 959 B |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -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;
|
||||
}
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Not Found"}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "451, Unavailable For Legal Reasons"}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "500, Internal Server Error"}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@@ -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" .}}
|
||||
|
@@ -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"}}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Apps"}}
|
||||
{{template "user_style" .}}
|
||||
|
||||
<style>
|
||||
.specs {
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Directory upload"}}
|
||||
{{template "user_style" . }}
|
||||
|
||||
<script>
|
||||
window.api_endpoint = '{{.APIEndpoint}}';
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "E-mail verification"}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "page_top" .}}
|
||||
|
@@ -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>
|
||||
|
@@ -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" />
|
||||
|
@@ -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" />
|
||||
|
@@ -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" />
|
||||
|
@@ -103,7 +103,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" .Title}}
|
||||
{{template "user_style" .}}
|
||||
<script>var apiEndpoint = '{{.APIEndpoint}}';</script>
|
||||
</head>
|
||||
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" .Title}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@@ -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" />
|
||||
|
@@ -1,6 +0,0 @@
|
||||
{{define "user_style"}}
|
||||
<style>
|
||||
{{.UserStyle}}
|
||||
{{template "layout.css" .}}
|
||||
</style>
|
||||
{{end}}
|
@@ -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>
|
||||
|
@@ -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 {
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Maintenance"}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@@ -3,7 +3,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Text upload"}}
|
||||
{{template "user_style" .}}
|
||||
|
||||
<script>
|
||||
window.api_endpoint = '{{.APIEndpoint}}';
|
||||
|
@@ -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>
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "File Manager"}}
|
||||
{{template "user_style" .}}
|
||||
|
||||
<script>
|
||||
window.api_endpoint = '{{.APIEndpoint}}';
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" .User.Username }}
|
||||
{{template "user_style" . }}
|
||||
|
||||
<script>
|
||||
window.api_endpoint = '{{.APIEndpoint}}';
|
||||
|
@@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Logging out..."}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "page_top" .}}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Free file sharing service"}}
|
||||
{{template "user_style" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "page_top" .}}
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
@@ -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/>
|
||||
|
@@ -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">
|
||||
|
@@ -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)}
|
||||
|
@@ -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.
|
||||
|
@@ -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},
|
||||
}
|
||||
|
@@ -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}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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)
|
||||
}
|
||||
|