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 module fornaxian.tech/pixeldrain_web
go 1.17 go 1.18
replace fornaxian.tech/pixeldrain_api_client => ../pixeldrain_api_client replace fornaxian.tech/pixeldrain_api_client => ../pixeldrain_api_client
require ( require (
fornaxian.tech/config v0.0.0-20211108212237-6133aed90586 fornaxian.tech/config v0.0.0-20211108212237-6133aed90586
fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640 fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640
fornaxian.tech/pixeldrain_api_client v0.0.0-20220305171318-e1197ab3d4c0 fornaxian.tech/pixeldrain_api_client v0.0.0-20220503161309-06b62641c05d
fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787 fornaxian.tech/util v0.0.0-20220603201140-7b74b1181b98
github.com/julienschmidt/httprouter v1.3.0 github.com/julienschmidt/httprouter v1.3.0
github.com/microcosm-cc/bluemonday v1.0.18 github.com/microcosm-cc/bluemonday v1.0.18
github.com/russross/blackfriday/v2 v2.1.0 github.com/russross/blackfriday/v2 v2.1.0
) )
require ( 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/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/golang/snappy v0.0.4 // indirect
github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/css v1.0.0 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // 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/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect
gopkg.in/inf.v0 v0.9.1 // 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 h1:/4a0Iq3cYeyTWcPHsN9pVAGJH3UTq1GapK253lHfXnE=
fornaxian.tech/config v0.0.0-20211108212237-6133aed90586/go.mod h1:ULIXF4J1DbBw4EsIPRNQDf6J3hl4P/jlihjy6UCm9FM= 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 h1:UPDxJwLRCfh/cv80UMSanzmZ0jIcfS1mcd0Y06HYuLw=
fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640/go.mod h1:sN82qMToeHhP2u3ehvrcE8y1IudRZJAZO9yG5OBYblo= 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-20220603201140-7b74b1181b98 h1:d0FsJgwiHunT4X6Hyz7FRBQF+ix/RDagKj2/2VnlY14=
fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787/go.mod h1:FqVgfghmxTGR3l9Zx4MOMeZ9KHjiEFl3s3C0BSTvBwk= fornaxian.tech/util v0.0.0-20220603201140-7b74b1181b98/go.mod h1:lCmtcb4/SVt2ol55/EHDWGySY7o0ONbj97RR9CdsN4M=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= 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/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= 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 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 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/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 v1.1.0 h1:ow36yzymDGsuKqnkecq2zR3prFkkbdzC/af5zTyPXNc=
github.com/gocql/gocql v0.0.0-20220224095938-0eacd3183625 h1:6ImvI6U901e1ezn/8u2z3bh1DZIvMOia0yTSBxhy4Ao= github.com/gocql/gocql v1.1.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/gocql/gocql v0.0.0-20220224095938-0eacd3183625/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
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/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
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/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-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-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.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= 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 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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. 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;"> <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> </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); background: var(--background);
min-height: 100vh; min-height: 100vh;
padding: 0; padding: 0;
transition: opacity 0.2s;
} }
header, header,
footer, footer,
.checkers { .checkers {
background-image: url("{{.BackgroundPattern}}"); background-image: var(--background_pattern);
background-color: var(--background_pattern_color); background-color: var(--background_pattern_color);
background-repeat: repeat; background-repeat: repeat;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
{{template "meta_tags" "Appearance settings"}} {{template "meta_tags" "Appearance settings"}}
{{template "user_style" .}} <link id="stylesheet_theme_2" rel="stylesheet" type="text/css" href="/theme.css"/>
</head> </head>
<body> <body>
@@ -24,6 +24,8 @@
<input type="radio" id="style_nord_dark" name="style"><label for="style_nord_dark">Nord dark</label> <input type="radio" id="style_nord_dark" name="style"><label for="style_nord_dark">Nord dark</label>
<br/> <br/>
<input type="radio" id="style_nord_light" name="style"><label for="style_nord_light">Nord light</label> <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/>
<br/> <br/>
<input type="radio" id="style_solarized" name="style"><label for="style_solarized">Solarized</label> <input type="radio" id="style_solarized" name="style"><label for="style_solarized">Solarized</label>
@@ -65,15 +67,41 @@
</section> </section>
<script> <script>
let style = "nord"
let hue = -1
// Style selector // Style selector
document.getElementsByName("style").forEach(function(elem) { document.getElementsByName("style").forEach(function(elem) {
elem.addEventListener("change", function(evt){ elem.addEventListener("change", e => {
var date = new Date(); style = e.target.id.substring(6)
date.setTime(date.getTime() + (10 * 365 * 24 * 60 * 60 * 1000)); setStyle()
document.cookie = "style=" + evt.target.id.substring(6) + "; expires=" + date.toUTCString() + "; path=/";
location.reload();
}) })
}); });
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> </script>
{{template "page_bottom" .}} {{template "page_bottom" .}}
{{template "analytics"}} {{template "analytics"}}

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,9 @@
<title>{{.Title}}</title> <title>{{.Title}}</title>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <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="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.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"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
{{ template "opengraph" .OGData }} {{ 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="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" /> <link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />

View File

@@ -5,7 +5,9 @@
<title>{{.Title}}</title> <title>{{.Title}}</title>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <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="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" /> <link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />

View File

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

View File

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

View File

@@ -3,6 +3,10 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="theme-color" content="#220735" /> <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="32x32" href="/res/img/pixeldrain_32.png" />
<link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" /> <link rel="icon" sizes="128x128" href="/res/img/pixeldrain_128.png" />
<link rel="icon" sizes="152x152" href="/res/img/pixeldrain_152.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"> <html lang="en">
<head> <head>
{{template "meta_tags" "Upload History"}} {{template "meta_tags" "Upload History"}}
{{template "user_style" .}}
</head> </head>
<body> <body>
{{template "page_top" .}} {{template "page_top" .}}
@@ -23,7 +22,93 @@
<script> <script>
let apiEndpoint = '{{.APIEndpoint}}'; 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> </script>
{{template "analytics"}} {{template "analytics"}}
</body> </body>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -65,7 +65,7 @@ onMount(() => {
<p> <p>
<strong> <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 <i class="icon">bolt</i> Support Pixeldrain on Patreon
</a> </a>
to disable the transfer limit to disable the transfer limit

View File

@@ -89,7 +89,7 @@ onMount(async () => {
<button on:click={() => {dispatch("download")}}> <button on:click={() => {dispatch("download")}}>
<i class="icon">download</i> Download <i class="icon">download</i> Download
</button> </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 <i class="icon">bolt</i> Support Pixeldrain on Patreon
</a> </a>
</div> </div>

View File

@@ -55,7 +55,7 @@ onMount(async () => {
{formatDuration((file.size/file.download_speed_limit)*1000)} {formatDuration((file.size/file.download_speed_limit)*1000)}
</li> </li>
<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 <i class="icon">bolt</i> Support Pixeldrain on Patreon
</a> </a>
and earn my eternal gratitude 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 still download the video and watch it locally on your computer without
an account. an account.
<br/> <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}> <button on:click={download}>
<i class="icon">download</i> Download <i class="icon">download</i> Download
</button> </button>
<a href="/register" class="button"> <a href="/register" class="button">
<i class="icon">how_to_reg</i> Sign up <i class="icon">how_to_reg</i> Sign up
</a> </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> </TextBlock>
<br/><br/> <br/><br/>

View File

@@ -53,7 +53,7 @@ onMount(() => {
Data transfer limit Data transfer limit
</div> </div>
<div class="feat_normal"> <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 your download speed will be reduced
</div> </div>
<div class="feat_pro"> <div class="feat_pro">

View File

@@ -264,9 +264,9 @@ onDestroy(() => {
{/if} {/if}
{#if transfer_cap === -1} {#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} {:else}
Paid transfers: Premium transfers:
{formatDataVolume(transfer_used, 3)} {formatDataVolume(transfer_used, 3)}
out of out of
{formatDataVolume(transfer_cap, 3)} {formatDataVolume(transfer_cap, 3)}

View File

@@ -2,6 +2,7 @@ package webcontroller
import ( import (
"fmt" "fmt"
"html/template"
"net/http" "net/http"
"strings" "strings"
"time" "time"
@@ -30,6 +31,29 @@ type fileViewerData struct {
ViewToken string `json:"view_token"` ViewToken string `json:"view_token"`
Embedded bool `json:"embedded"` Embedded bool `json:"embedded"`
UserAdsEnabled bool `json:"user_ads_enabled"` 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 // ServeFileViewer controller for GET /u/:id
@@ -95,10 +119,9 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
vd.Embedded = true vd.Embedded = true
} }
vd.themeOverride(r, files)
templateData.Other = vd templateData.Other = vd
fileStyleOverride(templateData, files)
for _, file := range files { for _, file := range files {
if file.AbuseType != "" { if file.AbuseType != "" {
w.WriteHeader(http.StatusUnavailableForLegalReasons) 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 { if _, ok := r.URL.Query()["embed"]; ok {
vd.Embedded = true vd.Embedded = true
} }
templateData.Other = vd
fileStyleOverride(templateData, list.Files) vd.themeOverride(r, list.Files)
templateData.Other = vd
for _, file := range list.Files { for _, file := range list.Files {
if file.AbuseType != "" { 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 // 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 // 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. // automatic checking of the presence of the ad unit on this page.

View File

@@ -1,17 +1,29 @@
package webcontroller package webcontroller
import ( import (
"bytes"
"fmt" "fmt"
"html/template" "html/template"
"math/rand" "math/rand"
"net/http" "net/http"
"strconv"
"time" "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) { func userStyleFromRequest(r *http.Request) (s template.CSS) {
// Get the chosen style from the URL // Get the chosen style from the URL
var style = r.URL.Query().Get("style") 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 the URL style was empty use the cookie value
if style == "" { if style == "" {
@@ -19,110 +31,175 @@ func userStyleFromRequest(r *http.Request) (s template.CSS) {
style = cookie.Value 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 { 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: 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 { type styleSheet struct {
Link hsl // Based on Highlight if undefined Link HSL // Based on Highlight if undefined
Input Color Input CSS
InputHover Color InputHover CSS
InputText Color InputText CSS
InputDisabledText Color InputDisabledText CSS
HighlightBackground Color HighlightBackground CSS
Highlight hsl // Links, highlighted buttons, list navigation Highlight HSL // Links, highlighted buttons, list navigation
HighlightText hsl // Text on buttons HighlightText HSL // Text on buttons
Danger hsl Danger HSL
ScrollbarForeground Color // Based on Highlight if undefined ScrollbarForeground CSS // Based on Highlight if undefined
ScrollbarHover Color // Based on ScrollbarForeground if undefined ScrollbarHover CSS // Based on ScrollbarForeground if undefined
BackgroundColor hsl BackgroundColor HSL
Background Color Background CSS
BackgroundText hsl BackgroundText HSL
BackgroundPattern Color BackgroundPattern CSS
ParallaxSlider Color ParallaxSlider CSS
Navigation Color Navigation CSS
BodyColor hsl BodyColor HSL
BodyBackground Color BodyBackground CSS
BodyText hsl BodyText HSL
Separator Color Separator CSS
CardColor hsl CardColor HSL
CardText hsl CardText HSL
// Colors to use in graphs // Colors to use in graphs
Chart1 hsl Chart1 HSL
Chart2 hsl Chart2 HSL
Chart3 hsl Chart3 HSL
Shadow hsl Shadow HSL
} }
func (s styleSheet) withDefaults() styleSheet { func (s styleSheet) withDefaults() styleSheet {
// Set default colors // Set default colors
var noColor = hsl{0, 0, 0} var noColor = HSL{0, 0, 0}
var defaultHSL = func(color *hsl, def hsl) { var defaultHSL = func(target *HSL, def HSL) {
if *color == noColor { if *target == noColor {
*color = def *target = def
} }
} }
var defaultColor = func(color *Color, def Color) { var defaultCSS = func(target *CSS, def CSS) {
if *color == nil { if *target == nil {
*color = def *target = def
} }
} }
defaultHSL(&s.Link, s.Highlight.Add(0, 0, -.05)) defaultHSL(&s.Link, s.Highlight.Add(0, 0, -.05))
defaultColor(&s.ScrollbarForeground, s.Input) defaultCSS(&s.ScrollbarForeground, s.Input)
defaultColor(&s.ScrollbarHover, s.Highlight) defaultCSS(&s.ScrollbarHover, s.Highlight)
defaultHSL(&s.Chart1, s.Highlight) defaultHSL(&s.Chart1, s.Highlight)
defaultHSL(&s.Chart2, s.Chart1.Add(120, 0, 0)) defaultHSL(&s.Chart2, s.Chart1.Add(120, 0, 0))
defaultHSL(&s.Chart3, s.Chart2.Add(120, 0, 0)) defaultHSL(&s.Chart3, s.Chart2.Add(120, 0, 0))
defaultColor(&s.HighlightBackground, s.Highlight) defaultCSS(&s.HighlightBackground, s.Highlight)
defaultColor(&s.Background, s.BackgroundColor) defaultCSS(&s.Background, s.BackgroundColor)
defaultColor(&s.BackgroundPattern, s.BackgroundColor) defaultCSS(&s.BackgroundPattern, s.BackgroundColor)
defaultColor(&s.ParallaxSlider, s.BackgroundColor) defaultCSS(&s.ParallaxSlider, s.BackgroundColor)
defaultColor(&s.Navigation, NoColor) defaultCSS(&s.Navigation, RawCSS("none"))
defaultColor(&s.BodyBackground, s.BodyColor) defaultCSS(&s.BodyBackground, s.BodyColor)
defaultHSL(&s.BackgroundText, s.BodyText) 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 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 { func (s styleSheet) String() string {
s = s.withDefaults() s = s.withDefaults()
@@ -144,6 +221,7 @@ func (s styleSheet) String() string {
--background_color: %s; --background_color: %s;
--background: %s; --background: %s;
--background_text_color: %s; --background_text_color: %s;
--background_pattern: url("%s");
--background_pattern_color: %s; --background_pattern_color: %s;
--parallax_slider_color: %s; --parallax_slider_color: %s;
--navigation_background: %s; --navigation_background: %s;
@@ -175,6 +253,7 @@ func (s styleSheet) String() string {
s.BackgroundColor.CSS(), s.BackgroundColor.CSS(),
s.Background.CSS(), s.Background.CSS(),
s.BackgroundText.CSS(), s.BackgroundText.CSS(),
BackgroundTiles(),
s.BackgroundPattern.CSS(), s.BackgroundPattern.CSS(),
s.ParallaxSlider.CSS(), s.ParallaxSlider.CSS(),
s.Navigation.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 ( var (
now = time.Now() now = time.Now()
month = now.Month() month = now.Month()
@@ -226,262 +305,264 @@ func BackgroundTiles(tpl *template.Template) template.URL {
file = fmt.Sprintf("checker%d", now.UnixNano()%18) file = fmt.Sprintf("checker%d", now.UnixNano()%18)
} }
var buf = bytes.Buffer{} return template.URL("/res/img/background_patterns/" + file + "_transparent.png")
if err := tpl.ExecuteTemplate(&buf, file+"_transparent.png", nil); err != nil {
panic(err) // var buf = bytes.Buffer{}
} // if err := tpl.ExecuteTemplate(&buf, file+"_transparent.png", nil); err != nil {
return template.URL(buf.String()) // panic(err)
// }
// return template.URL(buf.String())
} }
// Following are all the available styles // Following are all the available styles
var defaultPixeldrainStyle = styleSheet{ var purpleDrainStyle = styleSheet{
Input: hsl{266, .85, .24}, Input: HSL{266, .85, .24},
InputHover: hsl{266, .85, .28}, InputHover: HSL{266, .85, .28},
InputText: hsl{0, 0, .9}, InputText: HSL{0, 0, .9},
InputDisabledText: hsl{266, .85, .4}, InputDisabledText: HSL{266, .85, .4},
HighlightBackground: NewGradient(150, hsl{150, .84, .39}, hsl{85, .85, .35}), HighlightBackground: NewGradient(150, HSL{150, .84, .39}, HSL{85, .85, .35}),
Highlight: hsl{117, .63, .46}, Highlight: HSL{117, .63, .46},
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{357, .63, .46}, Danger: HSL{357, .63, .46},
ScrollbarForeground: hsl{266, .85, .40}, ScrollbarForeground: HSL{266, .85, .40},
ScrollbarHover: hsl{266, .85, .50}, ScrollbarHover: HSL{266, .85, .50},
BackgroundColor: hsl{273, .93, .12}, BackgroundColor: HSL{273, .93, .12},
Background: NewGradient(120, hsl{250, .9, .14}, hsl{300, .9, .10}), Background: NewGradient(120, HSL{250, .9, .14}, HSL{300, .9, .10}),
BackgroundPattern: NoColor, BackgroundPattern: RawCSS("none"),
ParallaxSlider: hsl{275, .8, .1}, ParallaxSlider: HSL{275, .8, .1},
Navigation: RGBA{0, 0, 0, 0.1}, Navigation: RGBA{0, 0, 0, 0.1},
BodyColor: hsl{274, .9, .14}, BodyColor: HSL{274, .9, .14},
BodyBackground: NoColor, BodyBackground: RawCSS("none"),
BodyText: hsl{0, 0, .8}, BodyText: HSL{0, 0, .8},
CardColor: hsl{275, .8, .18}, CardColor: HSL{275, .8, .18},
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var classicStyle = styleSheet{ var classicStyle = styleSheet{
Input: hsl{0, 0, .18}, Input: HSL{0, 0, .18},
InputHover: hsl{0, 0, .22}, InputHover: HSL{0, 0, .22},
InputText: hsl{0, 0, .9}, InputText: HSL{0, 0, .9},
InputDisabledText: hsl{0, 0, .4}, InputDisabledText: HSL{0, 0, .4},
Highlight: hsl{89, .60, .45}, Highlight: HSL{89, .60, .45},
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{339, .65, .31}, Danger: HSL{339, .65, .31},
ScrollbarForeground: hsl{0, 0, .40}, ScrollbarForeground: HSL{0, 0, .40},
ScrollbarHover: hsl{0, 0, .50}, ScrollbarHover: HSL{0, 0, .50},
BackgroundColor: hsl{0, 0, .08}, BackgroundColor: HSL{0, 0, .08},
BodyColor: hsl{0, 0, .12}, BodyColor: HSL{0, 0, .12},
BodyText: hsl{0, 0, .8}, BodyText: HSL{0, 0, .8},
CardColor: hsl{0, 0, .16}, CardColor: HSL{0, 0, .16},
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var maroonStyle = styleSheet{ var maroonStyle = styleSheet{
Input: hsl{0, .8, .20}, // hsl(0, 87%, 40%) Input: HSL{0, .8, .20}, // hsl(0, 87%, 40%)
InputHover: hsl{0, .8, .24}, InputHover: HSL{0, .8, .24},
InputText: hsl{0, 0, 1}, InputText: HSL{0, 0, 1},
InputDisabledText: hsl{0, 0, .5}, InputDisabledText: HSL{0, 0, .5},
Highlight: hsl{137, 1, .37}, //hsl(137, 100%, 37%) Highlight: HSL{137, 1, .37}, //hsl(137, 100%, 37%)
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{9, .96, .42}, //hsl(9, 96%, 42%) Danger: HSL{9, .96, .42}, //hsl(9, 96%, 42%)
ScrollbarForeground: hsl{0, .75, .3}, ScrollbarForeground: HSL{0, .75, .3},
ScrollbarHover: hsl{0, .75, .4}, ScrollbarHover: HSL{0, .75, .4},
BackgroundColor: hsl{0, .7, .05}, BackgroundColor: HSL{0, .7, .05},
BodyColor: hsl{0, .8, .08}, // hsl{0, .8, .15}, BodyColor: HSL{0, .8, .08}, // HSL{0, .8, .15},
BodyText: hsl{0, 0, .8}, BodyText: HSL{0, 0, .8},
CardColor: hsl{0, .9, .14}, CardColor: HSL{0, .9, .14},
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var hackerStyle = styleSheet{ var hackerStyle = styleSheet{
Input: hsl{0, 0, .1}, Input: HSL{0, 0, .1},
InputHover: hsl{0, 0, .14}, InputHover: HSL{0, 0, .14},
InputText: hsl{0, 0, 1}, InputText: HSL{0, 0, 1},
InputDisabledText: hsl{0, 0, .5}, InputDisabledText: HSL{0, 0, .5},
Highlight: hsl{120, .8, .5}, Highlight: HSL{120, .8, .5},
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{0, 1, .4}, Danger: HSL{0, 1, .4},
ScrollbarForeground: hsl{120, .5, .25}, ScrollbarForeground: HSL{120, .5, .25},
ScrollbarHover: hsl{120, .5, .35}, ScrollbarHover: HSL{120, .5, .35},
BackgroundColor: hsl{0, 0, 0}, BackgroundColor: HSL{0, 0, 0},
BodyColor: hsl{0, 0, .03}, BodyColor: HSL{0, 0, .03},
BodyText: hsl{0, 0, .8}, BodyText: HSL{0, 0, .8},
CardColor: hsl{120, .4, .05}, CardColor: HSL{120, .4, .05},
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var cantaPixeldrainStyle = styleSheet{ var cantaPixeldrainStyle = styleSheet{
Input: hsl{167, .06, .30}, // hsl(167, 6%, 30%) Input: HSL{167, .06, .30}, // hsl(167, 6%, 30%)
InputHover: hsl{167, .06, .34}, // hsl(167, 6%, 30%) InputHover: HSL{167, .06, .34}, // hsl(167, 6%, 30%)
InputText: hsl{0, 0, 1}, InputText: HSL{0, 0, 1},
InputDisabledText: hsl{0, 0, .5}, InputDisabledText: HSL{0, 0, .5},
Highlight: hsl{165, 1, .40}, // hsl(165, 100%, 40%) Highlight: HSL{165, 1, .40}, // hsl(165, 100%, 40%)
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{40, 1, .5}, // hsl(40, 100%, 50%) Danger: HSL{40, 1, .5}, // hsl(40, 100%, 50%)
ScrollbarForeground: hsl{204, .05, .78}, // hsl(204, 5%, 78%) ScrollbarForeground: HSL{204, .05, .78}, // hsl(204, 5%, 78%)
ScrollbarHover: hsl{204, .05, .88}, ScrollbarHover: HSL{204, .05, .88},
BackgroundColor: hsl{180, .04, .16}, BackgroundColor: HSL{180, .04, .16},
BodyColor: hsl{168, .05, .21}, BodyColor: HSL{168, .05, .21},
BodyText: hsl{0, 0, .8}, BodyText: HSL{0, 0, .8},
CardColor: hsl{170, .05, .26}, CardColor: HSL{170, .05, .26},
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var skeuosPixeldrainStyle = styleSheet{ var skeuosPixeldrainStyle = styleSheet{
Input: hsl{226, .15, .23}, //hsl(226, 15%, 23%) Input: HSL{226, .15, .23}, //hsl(226, 15%, 23%)
InputHover: hsl{226, .15, .27}, InputHover: HSL{226, .15, .27},
InputText: hsl{60, .06, .93}, InputText: HSL{60, .06, .93},
InputDisabledText: hsl{0, 0, .5}, InputDisabledText: HSL{0, 0, .5},
Highlight: hsl{282, .65, .54}, // hsl(282, 65%, 54%) Highlight: HSL{282, .65, .54}, // hsl(282, 65%, 54%)
HighlightText: hsl{0, 0, 1}, HighlightText: HSL{0, 0, 1},
Danger: hsl{0, .79, .43}, // hsl(0, 79%, 43%) Danger: HSL{0, .79, .43}, // hsl(0, 79%, 43%)
ScrollbarForeground: hsl{220, .02, .62}, // hsl(220, 2%, 62%) ScrollbarForeground: HSL{220, .02, .62}, // hsl(220, 2%, 62%)
ScrollbarHover: hsl{220, .02, .80}, ScrollbarHover: HSL{220, .02, .80},
BackgroundColor: hsl{232, .14, .11}, //hsl(232, 14%, 11%) BackgroundColor: HSL{232, .14, .11}, //hsl(232, 14%, 11%)
BodyColor: hsl{229, .14, .16}, // hsl(229, 14%, 16%) BodyColor: HSL{229, .14, .16}, // hsl(229, 14%, 16%)
BodyText: hsl{60, .06, .93}, // hsl(60, 6%, 93%) BodyText: HSL{60, .06, .93}, // hsl(60, 6%, 93%)
CardColor: hsl{225, .14, .17}, // hsl(225, 14%, 17%) CardColor: HSL{225, .14, .17}, // hsl(225, 14%, 17%)
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var nordDarkStyle = styleSheet{ var nordDarkStyle = styleSheet{
Input: hsl{220, .16, .36}, // nord3 Input: HSL{220, .16, .36}, // nord3
InputHover: hsl{220, .16, .40}, InputHover: HSL{220, .16, .40},
InputText: hsl{218, .27, .92}, // nord5 hsl(218, 27%, 92%) InputText: HSL{218, .27, .92}, // nord5 hsl(218, 27%, 92%)
InputDisabledText: hsl{220, .16, .22}, // nord0 hsl(220, 16%, 22%) InputDisabledText: HSL{220, .16, .22}, // nord0 hsl(220, 16%, 22%)
Highlight: hsl{92, .28, .65}, // nord14 hsl(92, 28%, 65%) Highlight: HSL{92, .28, .65}, // nord14 hsl(92, 28%, 65%)
HighlightText: hsl{220, .16, .22}, // nord0 HighlightText: HSL{220, .16, .22}, // nord0
Danger: hsl{354, .42, .56}, // nord11 hsl(354, 42%, 56%) Danger: HSL{354, .42, .56}, // nord11 hsl(354, 42%, 56%)
ScrollbarForeground: hsl{179, .25, .65}, // nord7 hsl(179, 25%, 65%) ScrollbarForeground: HSL{179, .25, .65}, // nord7 hsl(179, 25%, 65%)
ScrollbarHover: hsl{193, .43, .67}, // nord8 hsl(193, 43%, 67%) ScrollbarHover: HSL{193, .43, .67}, // nord8 hsl(193, 43%, 67%)
BackgroundColor: hsl{220, .16, .22}, // nord0 BackgroundColor: HSL{220, .16, .22}, // nord0
BodyColor: hsl{222, .16, .28}, // nord1 BodyColor: HSL{222, .16, .28}, // nord1
BodyText: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%) BodyText: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
CardColor: hsl{220, .17, .32}, // nord2 CardColor: HSL{220, .17, .32}, // nord2
Shadow: hsl{0, 0, 0}, Shadow: HSL{0, 0, 0},
} }
var nordLightStyle = styleSheet{ var nordLightStyle = styleSheet{
Link: hsl{92, .40, .32}, Link: HSL{92, .40, .32},
Input: hsl{218, .27, .94}, // nord6 hsl(218, 27%, 94%) Input: HSL{218, .27, .94}, // nord6 hsl(218, 27%, 94%)
InputHover: hsl{218, .27, .98}, InputHover: HSL{218, .27, .98},
InputText: hsl{222, .16, .28}, // nord1 hsl(222, 16%, 28%) InputText: HSL{222, .16, .28}, // nord1 hsl(222, 16%, 28%)
InputDisabledText: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%) InputDisabledText: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
Highlight: hsl{92, .28, .65}, // nord14 hsl(92, 28%, 65%) Highlight: HSL{92, .28, .65}, // nord14 hsl(92, 28%, 65%)
HighlightText: hsl{222, .16, .28}, // nord3 hsl(220, 16%, 36%) HighlightText: HSL{222, .16, .28}, // nord3 hsl(220, 16%, 36%)
Danger: hsl{354, .42, .56}, // nord11 hsl(354, 42%, 56%) Danger: HSL{354, .42, .56}, // nord11 hsl(354, 42%, 56%)
ScrollbarForeground: hsl{179, .25, .65}, // nord7 hsl(179, 25%, 65%) ScrollbarForeground: HSL{179, .25, .65}, // nord7 hsl(179, 25%, 65%)
ScrollbarHover: hsl{193, .43, .67}, // nord8 hsl(193, 43%, 67%) ScrollbarHover: HSL{193, .43, .67}, // nord8 hsl(193, 43%, 67%)
BackgroundColor: hsl{220, .16, .36}, // nord3 hsl(220, 16%, 36%) BackgroundColor: HSL{220, .16, .36}, // nord3 hsl(220, 16%, 36%)
BackgroundText: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%) BackgroundText: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
ParallaxSlider: hsl{220, .16, .22}, // nord0 hsl(220, 16%, 22%) ParallaxSlider: HSL{220, .16, .22}, // nord0 hsl(220, 16%, 22%)
BodyColor: hsl{219, .28, .88}, // nord4 hsl(219, 28%, 88%) BodyColor: HSL{219, .28, .88}, // nord4 hsl(219, 28%, 88%)
BodyText: hsl{220, .17, .32}, // nord2 hsl(220, 17%, 32%) BodyText: HSL{220, .17, .32}, // nord2 hsl(220, 17%, 32%)
BackgroundPattern: hsl{219, .28, .88}, // hsl(219, 28%, 88%) BackgroundPattern: HSL{219, .28, .88}, // hsl(219, 28%, 88%)
CardColor: hsl{218, .27, .92}, // nord5 hsl(218, 27%, 92%) CardColor: HSL{218, .27, .92}, // nord5 hsl(218, 27%, 92%)
Shadow: hsl{220, .16, .36}, Shadow: HSL{220, .16, .36},
} }
var sweetPixeldrainStyle = styleSheet{ var sweetPixeldrainStyle = styleSheet{
Input: hsl{229, .25, .18}, // hsl(229, 25%, 14%) Input: HSL{229, .25, .18}, // hsl(229, 25%, 14%)
InputHover: hsl{229, .25, .22}, // hsl(229, 25%, 14%) InputHover: HSL{229, .25, .22}, // hsl(229, 25%, 14%)
InputText: hsl{223, .13, .79}, InputText: HSL{223, .13, .79},
InputDisabledText: hsl{0, 0, .5}, InputDisabledText: HSL{0, 0, .5},
Highlight: hsl{296, .88, .44}, Highlight: HSL{296, .88, .44},
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{356, 1, .64}, // hsl(356, 100%, 64%) Danger: HSL{356, 1, .64}, // hsl(356, 100%, 64%)
BackgroundColor: hsl{225, .25, .06}, // hsl(225, 25%, 6%) BackgroundColor: HSL{225, .25, .06}, // hsl(225, 25%, 6%)
BodyColor: hsl{228, .25, .12}, // hsl(228, 25%, 12%) BodyColor: HSL{228, .25, .12}, // hsl(228, 25%, 12%)
BodyText: hsl{223, .13, .79}, // hsl(223, 13%, 79%) BodyText: HSL{223, .13, .79}, // hsl(223, 13%, 79%)
Separator: RGBA{255, 255, 255, 0.05}, 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{ var adwaitaDarkStyle = styleSheet{
Input: RGBA{255, 255, 255, .06}, Input: RGBA{255, 255, 255, .06},
InputHover: RGBA{255, 255, 255, .1}, InputHover: RGBA{255, 255, 255, .1},
InputText: hsl{0, 0, 1}, InputText: HSL{0, 0, 1},
InputDisabledText: hsl{0, 0, .5}, InputDisabledText: HSL{0, 0, .5},
Highlight: hsl{152, .62, .39}, // hsl(152, 62%, 39%) Highlight: HSL{152, .62, .39}, // hsl(152, 62%, 39%)
HighlightText: hsl{0, 0, 0}, HighlightText: HSL{0, 0, 0},
Danger: hsl{9, 1, .69}, // hsl(9, 100%, 69%) Danger: HSL{9, 1, .69}, // hsl(9, 100%, 69%)
BackgroundColor: hsl{0, 0, .19}, BackgroundColor: HSL{0, 0, .19},
BodyColor: hsl{0, 0, .14}, BodyColor: HSL{0, 0, .14},
BodyText: hsl{0, 0, 1}, BodyText: HSL{0, 0, 1},
Separator: RGBA{255, 255, 255, 0.04}, 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{ var adwaitaLightStyle = styleSheet{
Input: RGBA{0, 0, 0, .06}, Input: RGBA{0, 0, 0, .06},
InputHover: RGBA{0, 0, 0, .1}, InputHover: RGBA{0, 0, 0, .1},
InputText: hsl{0, 0, .2}, InputText: HSL{0, 0, .2},
InputDisabledText: hsl{0, 0, .7}, InputDisabledText: HSL{0, 0, .7},
Highlight: hsl{152, .62, .47}, // hsl(152, 62%, 47%) Highlight: HSL{152, .62, .47}, // hsl(152, 62%, 47%)
HighlightText: hsl{0, 0, 1}, HighlightText: HSL{0, 0, 1},
Danger: hsl{356, .75, .43}, // hsl(356, 75%, 43%) Danger: HSL{356, .75, .43}, // hsl(356, 75%, 43%)
BackgroundColor: hsl{0, 0, .92}, BackgroundColor: HSL{0, 0, .92},
BodyColor: hsl{0, 0, .98}, BodyColor: HSL{0, 0, .98},
BodyText: hsl{0, 0, .2}, BodyText: HSL{0, 0, .2},
CardColor: hsl{0, 0, 1}, CardColor: HSL{0, 0, 1},
Shadow: hsl{0, 0, 0.36}, Shadow: HSL{0, 0, 0.36},
} }
var solarizedDarkStyle = styleSheet{ var solarizedDarkStyle = styleSheet{
Input: hsl{192, .81, .18}, // hsl(194, 14%, 40%) Input: HSL{192, .81, .18}, // hsl(194, 14%, 40%)
InputHover: hsl{192, .81, .22}, // hsl(196, 13%, 45%) InputHover: HSL{192, .81, .22}, // hsl(196, 13%, 45%)
InputText: hsl{180, .07, .80}, // hsl(44, 87%, 94%) InputText: HSL{180, .07, .80}, // hsl(44, 87%, 94%)
InputDisabledText: hsl{194, .14, .30}, // hsl(194, 14%, 40%) InputDisabledText: HSL{194, .14, .30}, // hsl(194, 14%, 40%)
Highlight: hsl{68, 1, .30}, // hsl(68, 100%, 30%) Highlight: HSL{68, 1, .30}, // hsl(68, 100%, 30%)
HighlightText: hsl{192, .81, .14}, // hsl(192, 100%, 11%) HighlightText: HSL{192, .81, .14}, // hsl(192, 100%, 11%)
Danger: hsl{1, .71, .52}, // hsl(1, 71%, 52%) Danger: HSL{1, .71, .52}, // hsl(1, 71%, 52%)
BackgroundColor: hsl{192, 1, .11}, //hsl(192, 100%, 11%) BackgroundColor: HSL{192, 1, .11}, //hsl(192, 100%, 11%)
BodyColor: hsl{192, .81, .14}, // hsl(192, 81%, 14%) BodyColor: HSL{192, .81, .14}, // hsl(192, 81%, 14%)
BodyText: hsl{180, .07, .60}, // hsl(180, 7%, 60%) BodyText: HSL{180, .07, .60}, // hsl(180, 7%, 60%)
Separator: RGBA{255, 255, 255, 0.05}, 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{ var solarizedLightStyle = styleSheet{
Input: hsl{46, .42, .84}, //hsl(180, 7%, 60%) Input: HSL{46, .42, .84}, //hsl(180, 7%, 60%)
InputHover: hsl{46, .42, .88}, InputHover: HSL{46, .42, .88},
InputText: hsl{194, .14, .20}, // hsl(192, 81%, 14%) InputText: HSL{194, .14, .20}, // hsl(192, 81%, 14%)
InputDisabledText: hsl{194, .14, .80}, InputDisabledText: HSL{194, .14, .80},
Highlight: hsl{68, 1, .30}, // hsl(68, 100%, 30%) Highlight: HSL{68, 1, .30}, // hsl(68, 100%, 30%)
HighlightText: hsl{44, .87, .94}, HighlightText: HSL{44, .87, .94},
Danger: hsl{1, .71, .52}, // hsl(1, 71%, 52%) Danger: HSL{1, .71, .52}, // hsl(1, 71%, 52%)
BackgroundColor: hsl{46, .42, .88}, // hsl(46, 42%, 88%) BackgroundColor: HSL{46, .42, .88}, // hsl(46, 42%, 88%)
BodyColor: hsl{44, .87, .94}, // hsl(44, 87%, 94%) BodyColor: HSL{44, .87, .94}, // hsl(44, 87%, 94%)
BodyText: hsl{194, .14, .40}, // hsl(194, 14%, 40%) BodyText: HSL{194, .14, .40}, // hsl(194, 14%, 40%)
Separator: RGBA{0, 0, 0, 0.05}, 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 ( import (
"fmt" "fmt"
"math"
) )
type Color interface { type Color interface {
CSS
HSL() HSL
RGB() RGB
}
type CSS interface {
CSS() string CSS() string
} }
// Raw CSS // Raw CSS
type CSS string type RawCSS string
func (c CSS) CSS() string { return string(c) } func (c RawCSS) CSS() string { return string(c) }
const NoColor = CSS("none")
// HSL color // HSL color
type hsl struct { type HSL struct {
Hue int Hue int
Saturation float64 Saturation float64
Lightness 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 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 { if s == 0 {
r, g, b = l, l, l r, g, b = l, l, l
@@ -58,19 +67,15 @@ func (orig hsl) RGB() string {
g = hue2rgb(p, q, h) g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h-1.0/3.0) b = hue2rgb(p, q, h-1.0/3.0)
} }
return RGB{R: uint8(r * 255), G: uint8(g * 255), B: uint8(b * 255)}
return fmt.Sprintf("%02x%02x%02x", int(r*255), int(g*255), int(b*255))
}
func (orig hsl) CSS() string {
return "#" + orig.RGB()
} }
// Add returns a NEW HSL struct, it doesn't modify the current one // Add returns a NEW HSL struct, it doesn't modify the current one
func (h hsl) Add(hue int, saturation float64, lightness float64) hsl { func (hsl HSL) Add(hue int, saturation float64, lightness float64) HSL {
var new = hsl{ var new = HSL{
h.Hue + hue, hsl.Hue + hue,
h.Saturation + saturation, hsl.Saturation + saturation,
h.Lightness + lightness, hsl.Lightness + lightness,
} }
// Hue bounds correction // Hue bounds correction
if new.Hue < 0 { if new.Hue < 0 {
@@ -94,21 +99,27 @@ func (h hsl) Add(hue int, saturation float64, lightness float64) hsl {
return new return new
} }
func (h hsl) WithAlpha(alpha float64) HSLA { func (hsl HSL) WithAlpha(alpha float64) HSLA {
return HSLA{h, alpha} return HSLA{hsl.Hue, hsl.Saturation, hsl.Lightness, alpha}
} }
type HSLA struct { type HSLA struct {
hsl Hue int
Saturation float64
Lightness float64
Alpha float64 Alpha float64
} }
var _ Color = HSLA{}
func (hsla HSLA) CSS() string { func (hsla HSLA) CSS() string {
return fmt.Sprintf( return fmt.Sprintf(
"hsla(%d, %.2f%%, %.2f%%, %.2f)", "hsla(%d, %.2f%%, %.2f%%, %.2f)",
hsla.Hue, hsla.Saturation*100, hsla.Lightness*100, hsla.Alpha, 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 { type RGB struct {
R uint8 R uint8
@@ -116,9 +127,55 @@ type RGB struct {
B uint8 B uint8
} }
func (rgb RGB) CSS() string { var _ Color = RGB{}
return fmt.Sprintf("#%02x%02x%02x", rgb.R, rgb.G, rgb.B)
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 { type RGBA struct {
R uint8 R uint8
@@ -127,15 +184,22 @@ type RGBA struct {
A float64 A float64
} }
var _ Color = RGBA{}
func (rgba RGBA) CSS() string { func (rgba RGBA) CSS() string {
return fmt.Sprintf("rgba(%d, %d, %d, %f)", rgba.R, rgba.G, rgba.B, rgba.A) 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 { type Gradient struct {
Angle int Angle int
Colors []Color Colors []Color
} }
var _ CSS = Gradient{}
func NewGradient(angle int, colors ...Color) Gradient { func NewGradient(angle int, colors ...Color) Gradient {
return Gradient{angle, colors} return Gradient{angle, colors}
} }

View File

@@ -25,8 +25,6 @@ type TemplateData struct {
Authenticated bool Authenticated bool
User pixelapi.UserInfo User pixelapi.UserInfo
UserAgent string UserAgent string
UserStyle template.CSS
BackgroundPattern template.URL
APIEndpoint template.URL APIEndpoint template.URL
PixelAPI pixelapi.PixelAPI PixelAPI pixelapi.PixelAPI
Hostname template.HTML Hostname template.HTML
@@ -45,11 +43,6 @@ type TemplateData struct {
Form Form 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) { func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) (t *TemplateData) {
t = &TemplateData{ t = &TemplateData{
tpm: wc.templates, tpm: wc.templates,
@@ -65,8 +58,6 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
URLQuery: r.URL.Query(), URLQuery: r.URL.Query(),
} }
t.setStyle(userStyleFromRequest(r))
// If the user is authenticated we'll indentify him and put the user info // 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 // into the templatedata. This is used for putting the username in the menu
// and stuff like that // 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) div(a, b interface{}) float64 { return toFloat(a) / toFloat(b) }
func (tm *TemplateManager) formatData(i interface{}) string { 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 { func (tm *TemplateManager) formatSC(amt float64) string {
var fmtSize = func(n float64, u string) string { var fmtSize = func(n float64, u string) string {

View File

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