Remove old file viewer
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,5 @@
|
||||
.vscode
|
||||
main
|
||||
pdwebconf.toml
|
||||
go.sum
|
||||
svelte/node_modules
|
||||
res/static/svelte/*
|
||||
|
69
go.sum
Normal file
69
go.sum
Normal file
@@ -0,0 +1,69 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70 h1:yRkXab8h+BAWEphLE0qexJVxIOdPgw+3T9VSLuyPXus=
|
||||
github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70/go.mod h1:Ig5am30IOP/eqsjogI1TuSlOTIeTPHoMOpYYM1bisww=
|
||||
github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3 h1:PfKr7anK3z4kLG9V6BbbKOVFhVaGEAJi4HxXCAa+QeU=
|
||||
github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3/go.mod h1:jdnyerqAlXJJpQmpyrdmSYMitRaRZ8RejEXuXz6n5QY=
|
||||
github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145 h1:2a8cFtVwEvK7NeimwAEoSUdf4hC80cXpnj3s4pHga+c=
|
||||
github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145/go.mod h1:Ew6h8nlacK6H8aABMDUYN3uaO4Rpw2HLKQZ2ntEybqM=
|
||||
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=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
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/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
|
||||
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
|
||||
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jhillyerd/enmime v0.8.4/go.mod h1:SWWlqKsXJMl00Nnuh04RSu6XoEo83B/VaujD/xzoBP0=
|
||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/scylladb/gocql v1.5.0 h1:tWaA08A8IprjgtBNPTVn8RkdiwEFUc85VcLA0E8JjH0=
|
||||
github.com/scylladb/gocql v1.5.0/go.mod h1:S154F0u6zQlF3JjuHAidQIExQf9H45yT8z68h0FQYdU=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||
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 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
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/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
@@ -1,65 +0,0 @@
|
||||
Chart.defaults.global.defaultFontColor = "#b3b3b3";
|
||||
Chart.defaults.global.defaultFontSize = 15;
|
||||
Chart.defaults.global.defaultFontFamily = "system-ui, sans-serif";
|
||||
Chart.defaults.global.maintainAspectRatio = false;
|
||||
Chart.defaults.global.elements.point.radius = 0;
|
||||
Chart.defaults.global.tooltips.mode = "index";
|
||||
Chart.defaults.global.tooltips.axis = "x";
|
||||
Chart.defaults.global.tooltips.intersect = false;
|
||||
Chart.defaults.global.animation.duration = 500;
|
||||
Chart.defaults.global.animation.easing = "linear";
|
||||
|
||||
function drawGraph(element, label, dataType) {
|
||||
return new Chart(
|
||||
element,
|
||||
{
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: label,
|
||||
backgroundColor: "#" + window.style.highlightColor,
|
||||
borderWidth: 0,
|
||||
lineTension: 0,
|
||||
fill: true,
|
||||
yAxisID: "ax_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
legend: { display: false },
|
||||
scales: {
|
||||
yAxes: [
|
||||
{
|
||||
type: "linear",
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "ax_1",
|
||||
ticks: {
|
||||
callback: function (value, index, values) {
|
||||
if (dataType == "bytes") {
|
||||
return formatDataVolume(value, 3);
|
||||
}
|
||||
return formatNumber(value, 3);
|
||||
},
|
||||
beginAtZero: true
|
||||
},
|
||||
gridLines: { display: true },
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
ticks: {
|
||||
sampleSize: 1,
|
||||
padding: 4,
|
||||
minRotation: 0,
|
||||
maxRotation: 0
|
||||
},
|
||||
gridLines: { display: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
function AbuseReportWindow(viewer) {
|
||||
this.viewer = viewer
|
||||
this.visible = false
|
||||
this.modal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
() => { this.toggle() },
|
||||
"Report abuse", "650px", "auto",
|
||||
)
|
||||
|
||||
this.btnReportAbuse = document.getElementById("btn_report_abuse")
|
||||
this.btnReportAbuse.addEventListener("click", () => { this.toggle() })
|
||||
|
||||
let clone = document.getElementById("tpl_report_abuse_popup").content.cloneNode(true)
|
||||
this.form = clone.querySelector(".abuse_type_form")
|
||||
// this.emailField = clone.querySelector(".abuse_email_field")
|
||||
this.notification = clone.querySelector(".abuse_report_notification")
|
||||
this.modal.setBody(clone)
|
||||
|
||||
this.form.addEventListener("submit", e => { this.submit(e) })
|
||||
}
|
||||
|
||||
AbuseReportWindow.prototype.toggle = function () {
|
||||
if (this.visible) {
|
||||
this.modal.close()
|
||||
this.btnReportAbuse.classList.remove("button_highlight")
|
||||
this.visible = false
|
||||
} else {
|
||||
this.modal.open()
|
||||
this.btnReportAbuse.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
AbuseReportWindow.prototype.notify = function (success, content) {
|
||||
this.notification.style.display = ""
|
||||
this.notification.classList = "abuse_report_notification " + (success ? "highlight_green" : "highlight_red")
|
||||
this.notification.innerHTML = content
|
||||
}
|
||||
|
||||
AbuseReportWindow.prototype.submit = async function (e) {
|
||||
e.preventDefault()
|
||||
|
||||
let abuseType = ""
|
||||
this.form.querySelectorAll('[name="abuse_type"]').forEach(elem => {
|
||||
if (elem.checked) {
|
||||
abuseType = elem.value
|
||||
}
|
||||
})
|
||||
|
||||
if (abuseType === "") {
|
||||
this.notify(false, "Please select an abuse type")
|
||||
return
|
||||
}
|
||||
|
||||
const form = new FormData()
|
||||
form.append("type", abuseType)
|
||||
// form.append("email", this.emailField.value)
|
||||
|
||||
try {
|
||||
const resp = await fetch(
|
||||
this.viewer.file.get_href + "/report_abuse",
|
||||
{ method: "POST", body: form }
|
||||
);
|
||||
if (resp.status >= 400) {
|
||||
let json = await resp.json()
|
||||
if (json.value === "resource_already_exists") {
|
||||
throw "You have already reported this file"
|
||||
} else if (json.value === "file_already_blocked") {
|
||||
throw "This file has already been blocked"
|
||||
} else if (json.value === "multiple_errors") {
|
||||
throw json.errors[0].message
|
||||
}
|
||||
throw json.message
|
||||
}
|
||||
|
||||
this.notify(true, "Report has been sent")
|
||||
} catch (err) {
|
||||
this.notify(false, "Failed to send report: " + err)
|
||||
}
|
||||
}
|
@@ -1,103 +0,0 @@
|
||||
function DetailsWindow(viewer) {
|
||||
this.viewer = viewer
|
||||
this.visible = false
|
||||
this.file = null
|
||||
this.graphsInitialized = false
|
||||
this.graphViews = 0
|
||||
this.graphDownloads = 0
|
||||
this.modal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
() => { this.toggle() },
|
||||
"File Details", "1200px", "1000px",
|
||||
)
|
||||
|
||||
let clone = document.getElementById("tpl_details_popup").content.cloneNode(true)
|
||||
this.divFileDetails = clone.querySelector(".info_file_details")
|
||||
this.modal.setBody(clone)
|
||||
|
||||
this.btnDetails = document.getElementById("btn_details")
|
||||
this.btnDetails.addEventListener("click", () => { this.toggle() })
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.toggle = function () {
|
||||
if (this.visible) {
|
||||
this.modal.close()
|
||||
this.btnDetails.classList.remove("button_highlight")
|
||||
this.visible = false
|
||||
} else {
|
||||
this.modal.open()
|
||||
this.btnDetails.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
|
||||
if (!this.graphsInitialized) {
|
||||
this.renderGraphs()
|
||||
this.graphsInitialized = true
|
||||
}
|
||||
this.updateGraph(this.file)
|
||||
}
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.setFile = function (file) {
|
||||
this.file = file
|
||||
let desc = ""
|
||||
if (this.viewer.isList) {
|
||||
desc = file.description
|
||||
}
|
||||
this.divFileDetails.innerHTML = `<tr><td>Name<td><td>${escapeHTML(file.name)}</td></tr>
|
||||
<tr><td>URL<td><td><a href="${file.link}">${file.link}</a></td></tr>
|
||||
<tr><td>Mime Type<td><td>${escapeHTML(file.mime_type)}</td></tr>
|
||||
<tr><td>ID<td><td>${file.id}</td></tr>
|
||||
<tr><td>Size<td><td>${formatDataVolume(file.size, 4)} ( ${formatThousands(file.size)} B )</td></tr>
|
||||
<tr><td>Bandwidth<td><td>${formatDataVolume(file.bandwidth_used, 4)}</td></tr>
|
||||
<tr><td>Upload Date<td><td>${printDate(file.date_created, true, true, true)}</td></tr>
|
||||
<tr><td>Description<td><td>${escapeHTML(desc)}</td></tr>`
|
||||
|
||||
if (this.visible && file.timeseries_href !== "") {
|
||||
this.updateGraph(file)
|
||||
}
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.renderGraphs = function () {
|
||||
console.log("rendering graphs")
|
||||
this.graphDownloads = drawGraph(
|
||||
document.getElementById("downloads_chart"), "Downloads", "number",
|
||||
);
|
||||
this.graphViews = drawGraph(
|
||||
document.getElementById("views_chart"), "Views", "number",
|
||||
);
|
||||
}
|
||||
|
||||
DetailsWindow.prototype.updateGraph = function (file) {
|
||||
console.log("updating graph")
|
||||
|
||||
let today = new Date()
|
||||
let start = new Date()
|
||||
start.setDate(start.getDate() - 90)
|
||||
|
||||
fetch(
|
||||
file.timeseries_href +
|
||||
"?start=" + start.toISOString() +
|
||||
"&end=" + today.toISOString() +
|
||||
"&interval=" + 60
|
||||
).then(resp => {
|
||||
if (!resp.ok) { return null }
|
||||
return resp.json()
|
||||
}).then(resp => {
|
||||
resp.views.timestamps.forEach((val, idx) => {
|
||||
let date = new Date(val);
|
||||
let dateStr = ("00" + (date.getMonth() + 1)).slice(-2);
|
||||
dateStr += "-" + ("00" + date.getDate()).slice(-2);
|
||||
dateStr += " " + ("00" + date.getHours()).slice(-2) + "h";
|
||||
resp.views.timestamps[idx] = " " + dateStr + " "; // Poor man's padding
|
||||
});
|
||||
resp.bandwidth.amounts.forEach((val, idx) => {
|
||||
resp.bandwidth.amounts[idx] = Math.round(val / file.size);
|
||||
});
|
||||
this.graphDownloads.data.labels = resp.views.timestamps
|
||||
this.graphViews.data.labels = resp.views.timestamps
|
||||
this.graphDownloads.data.datasets[0].data = resp.bandwidth.amounts
|
||||
this.graphViews.data.datasets[0].data = resp.views.amounts
|
||||
this.graphDownloads.update()
|
||||
this.graphViews.update()
|
||||
})
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
function EditWindow() {
|
||||
this.visible = false
|
||||
this.modal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
() => { this.toggle() },
|
||||
"Edit File", "1000px", "auto",
|
||||
)
|
||||
|
||||
let clone = document.getElementById("tpl_edit_file").content.cloneNode(true)
|
||||
this.notification = clone.querySelector(".edit_file_notification")
|
||||
this.fileNameField = clone.querySelector(".edit_file_name_field")
|
||||
|
||||
clone.querySelector(".btn_delete_file").addEventListener("click", () => { this.deleteFile() })
|
||||
clone.querySelector(".edit_file_name_form").addEventListener("submit", e => { this.renameFile(e) })
|
||||
|
||||
this.modal.setBody(clone)
|
||||
|
||||
this.btnEdit = document.getElementById("btn_edit")
|
||||
this.btnEdit.addEventListener("click", () => { this.toggle() })
|
||||
}
|
||||
|
||||
EditWindow.prototype.toggle = function () {
|
||||
if (this.visible) {
|
||||
this.modal.close()
|
||||
this.btnEdit.classList.remove("button_highlight")
|
||||
this.visible = false
|
||||
} else if (!this.visible && this.file.can_edit) {
|
||||
this.modal.open()
|
||||
this.btnEdit.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
EditWindow.prototype.setFile = function (file) {
|
||||
this.file = file
|
||||
this.modal.setTitle("Editing " + file.name)
|
||||
this.notification.style.display = "none"
|
||||
this.fileNameField.value = file.name
|
||||
|
||||
if (this.file.can_edit) {
|
||||
this.btnEdit.style.display = ""
|
||||
} else {
|
||||
this.btnEdit.style.display = "none"
|
||||
}
|
||||
}
|
||||
|
||||
EditWindow.prototype.notify = function (success, content) {
|
||||
this.notification.style.display = ""
|
||||
this.notification.classList = "edit_file_notification " + (success ? "highlight_green" : "highlight_red")
|
||||
this.notification.innerHTML = content
|
||||
}
|
||||
|
||||
EditWindow.prototype.deleteFile = async function () {
|
||||
if (!confirm("Are you sure you want to delete '" + this.file.name + "'?")) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const resp = await fetch(this.file.get_href, { method: "DELETE" });
|
||||
if (resp.status >= 400) {
|
||||
throw (await resp.json()).message
|
||||
}
|
||||
|
||||
this.notify(true, "This file has been deleted, you can close the page")
|
||||
} catch (err) {
|
||||
this.notify(false, "Could not delete file: " + err)
|
||||
}
|
||||
}
|
||||
|
||||
EditWindow.prototype.renameFile = async function (e) {
|
||||
e.preventDefault()
|
||||
|
||||
const form = new FormData()
|
||||
form.append("action", "rename")
|
||||
form.append("name", this.fileNameField.value)
|
||||
|
||||
try {
|
||||
const resp = await fetch(this.file.get_href, { method: "POST", body: form });
|
||||
if (resp.status >= 400) {
|
||||
throw (await resp.json()).message
|
||||
}
|
||||
|
||||
this.notify(true, "File name has been changed. Reload the page to see the changes")
|
||||
} catch (err) {
|
||||
this.notify(false, "Could not change file name: " + err)
|
||||
}
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
function EmbedWindow(viewer) {
|
||||
this.viewer = viewer
|
||||
this.visible = false
|
||||
this.modal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
() => { this.toggle() },
|
||||
"Embed file", "850px", "auto",
|
||||
)
|
||||
|
||||
let clone = document.getElementById("tpl_embed_popup").content.cloneNode(true)
|
||||
this.textarea = clone.querySelector(".embed_html_code")
|
||||
this.previewArea = clone.querySelector(".embed_preview_area")
|
||||
this.btnCopyHTML = clone.querySelector(".embed_copy_html")
|
||||
this.btnShowPreview = clone.querySelector(".embed_show_preview")
|
||||
this.modal.setBody(clone)
|
||||
|
||||
this.btnCopyHTML.addEventListener("click", () => { this.copyHTML() })
|
||||
this.btnShowPreview.addEventListener("click", () => { this.showPreview() })
|
||||
|
||||
this.btnEmbed = document.getElementById("btn_embed")
|
||||
this.btnEmbed.addEventListener("click", () => { this.toggle() })
|
||||
|
||||
this.updateCode()
|
||||
}
|
||||
|
||||
EmbedWindow.prototype.toggle = function () {
|
||||
if (this.visible) {
|
||||
this.modal.close()
|
||||
this.btnEmbed.classList.remove("button_highlight")
|
||||
this.visible = false
|
||||
} else {
|
||||
this.modal.open()
|
||||
this.btnEmbed.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
EmbedWindow.prototype.updateCode = function () {
|
||||
let url
|
||||
if (this.viewer.isFile) {
|
||||
url = domainURL() + "/u/" + this.viewer.file.id + "?embed"
|
||||
} else {
|
||||
url = domainURL() + "/l/" + this.viewer.listId + "?embed"
|
||||
}
|
||||
|
||||
this.textarea.value = `<iframe ` +
|
||||
`src="${url}" ` +
|
||||
`style="border: none; width: 800px; max-width: 100%; height: 500px; border-radius: 16px;"` +
|
||||
`></iframe>`
|
||||
}
|
||||
|
||||
EmbedWindow.prototype.copyHTML = function () {
|
||||
if (copyText(this.textarea.value)) {
|
||||
console.log('Text copied')
|
||||
this.btnCopyHTML.innerHTML = `<i class="icon">content_copy</i> Copied!`
|
||||
this.btnCopyHTML.classList.add("button_highlight")
|
||||
} else {
|
||||
console.log('Copying not supported')
|
||||
this.btnCopyHTML.innerText = "Error!"
|
||||
alert("Your browser does not support copying text.")
|
||||
}
|
||||
}
|
||||
|
||||
EmbedWindow.prototype.showPreview = function () {
|
||||
this.previewArea.innerHTML = this.textarea.value
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
function IntroPopup() {
|
||||
if (localStorage.getItem("viewer_intro_popup_dismissed") === "🍆") {
|
||||
return
|
||||
}
|
||||
|
||||
let btnHome = document.getElementById("button_home")
|
||||
|
||||
this.popup = document.createElement("div")
|
||||
this.popup.classList = "intro_popup"
|
||||
this.moveToElement(btnHome)
|
||||
|
||||
let clone = document.getElementById("intro_popup").content.cloneNode(true)
|
||||
clone.querySelector(".intro_popup_close").addEventListener("click", () => { this.close() })
|
||||
this.popup.append(clone)
|
||||
|
||||
document.getElementById("file_viewer").append(this.popup)
|
||||
|
||||
// Sometimes the layout is not correctly calculated yet when this script
|
||||
// runs. We adjust the values later
|
||||
setTimeout(() => { this.moveToElement(btnHome) }, 400)
|
||||
}
|
||||
|
||||
IntroPopup.prototype.moveToElement = function (el) {
|
||||
let rect = el.getBoundingClientRect()
|
||||
this.popup.style.top = (rect.top + el.offsetHeight + 20) + "px"
|
||||
this.popup.style.left = (rect.left + (el.clientWidth / 2) - 40) + "px"
|
||||
}
|
||||
|
||||
IntroPopup.prototype.close = function () {
|
||||
localStorage.setItem("viewer_intro_popup_dismissed", "🍆")
|
||||
this.popup.style.opacity = 0
|
||||
|
||||
setTimeout(() => { this.popup.remove() }, 500)
|
||||
}
|
@@ -1,178 +0,0 @@
|
||||
function ListNavigator(viewer, files) {
|
||||
this.viewer = viewer
|
||||
this.files = files
|
||||
this.length = files.length
|
||||
this.position = 0
|
||||
this.history = []
|
||||
this.shuffle = false
|
||||
|
||||
this.divListNavigator = document.getElementById("list_navigator")
|
||||
|
||||
this.btnDownloadList = document.getElementById("btn_download_list")
|
||||
if (files.id !== "") {
|
||||
this.btnDownloadList.style.display = ""
|
||||
this.btnDownloadList.addEventListener("click", () => { this.downloadList() })
|
||||
}
|
||||
this.btnShuffle = document.getElementById("btn_shuffle")
|
||||
this.btnShuffle.style.display = ""
|
||||
this.btnShuffle.addEventListener("click", () => { this.toggleShuffle() })
|
||||
|
||||
// Render list contents in list navigator div
|
||||
files.forEach((item, i) => {
|
||||
let filename
|
||||
if(item.name !== "null"){
|
||||
filename = item.name
|
||||
}else{
|
||||
filename = "Removed File"
|
||||
}
|
||||
|
||||
let d = document.createElement("div")
|
||||
d.classList = "file_button list_item"
|
||||
d.addEventListener("click", () => { this.setItem(i) })
|
||||
d.innerText = filename
|
||||
this.divListNavigator.appendChild(d)
|
||||
})
|
||||
|
||||
// Make the navigator visible
|
||||
this.divListNavigator.style.display = "inline-block"
|
||||
|
||||
// Skip to the file defined in the link hash
|
||||
let matches = location.hash.match(new RegExp('item=([^&]*)'))
|
||||
let hashID = matches ? matches[1] : null
|
||||
|
||||
if(Number.isInteger(parseInt(hashID))){
|
||||
this.setItem(parseInt(hashID))
|
||||
}else{
|
||||
this.setItem(0)
|
||||
}
|
||||
}
|
||||
|
||||
ListNavigator.prototype.nextItem = function() {
|
||||
if(this.shuffle){
|
||||
this.randItem()
|
||||
return
|
||||
}
|
||||
|
||||
if (this.position >= this.length) {
|
||||
this.position = 0
|
||||
} else {
|
||||
this.position++
|
||||
}
|
||||
|
||||
this.setItem(this.position)
|
||||
}
|
||||
|
||||
ListNavigator.prototype.previousItem = function() {
|
||||
if(this.position === 0){
|
||||
this.position = this.length - 1
|
||||
}else{
|
||||
this.position--
|
||||
}
|
||||
|
||||
this.setItem(this.position)
|
||||
}
|
||||
|
||||
ListNavigator.prototype.randItem = function() {
|
||||
// Avoid viewing the same file multiple times
|
||||
let rand
|
||||
do {
|
||||
rand = Math.round(Math.random() * this.length)
|
||||
console.log("rand is " + rand)
|
||||
} while(this.history.indexOf(rand) > -1)
|
||||
|
||||
this.setItem(rand)
|
||||
}
|
||||
|
||||
ListNavigator.prototype.setItem = function(index) {
|
||||
if(index >= this.length){
|
||||
this.position = 0
|
||||
}else{
|
||||
this.position = index
|
||||
}
|
||||
|
||||
// Set the URL hash
|
||||
location.hash = "item=" + this.position
|
||||
this.viewer.setFile(this.files[this.position])
|
||||
|
||||
this.addToHistory(index)
|
||||
this.loadThumbnails(index)
|
||||
|
||||
document.querySelectorAll("#list_navigator > .file_button_selected").forEach(el => {
|
||||
el.classList.remove("file_button_selected")
|
||||
})
|
||||
|
||||
let selectedItem = this.divListNavigator.children[this.position]
|
||||
selectedItem.classList.add("file_button_selected")
|
||||
|
||||
let cst = window.getComputedStyle(selectedItem)
|
||||
let itemWidth = selectedItem.offsetWidth + parseInt(cst.marginLeft) + parseInt(cst.marginRight)
|
||||
|
||||
let start = this.divListNavigator.scrollLeft
|
||||
let end = ((this.position * itemWidth) + (itemWidth / 2)) - (this.divListNavigator.clientWidth / 2)
|
||||
let steps = 60 // One second
|
||||
let stepSize = (end - start)/steps
|
||||
|
||||
let animateScroll = (pos, step) => {
|
||||
this.divListNavigator.scrollLeft = pos
|
||||
|
||||
if (step < steps) {
|
||||
requestAnimationFrame(() => {
|
||||
animateScroll(pos+stepSize, step+1)
|
||||
})
|
||||
}
|
||||
}
|
||||
animateScroll(start, 0)
|
||||
}
|
||||
|
||||
ListNavigator.prototype.downloadList = function() {
|
||||
document.getElementById("download_frame").src = "/api/list/" + this.viewer.listId + "/zip"
|
||||
}
|
||||
|
||||
ListNavigator.prototype.addToHistory = function(index) {
|
||||
if(this.history.length >= (this.length - 6)){
|
||||
this.history.shift()
|
||||
}
|
||||
this.history.push(index)
|
||||
}
|
||||
|
||||
ListNavigator.prototype.toggleShuffle = function() {
|
||||
this.shuffle = !this.shuffle // :P
|
||||
|
||||
if(this.shuffle){
|
||||
document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle ☑" // Check icon
|
||||
this.btnShuffle.classList.add("button_highlight")
|
||||
}else{
|
||||
document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle ☐" // Empty checkbox
|
||||
this.btnShuffle.classList.remove("button_highlight")
|
||||
}
|
||||
}
|
||||
|
||||
ListNavigator.prototype.loadThumbnails = function(index) {
|
||||
let startPos = +index - 50
|
||||
let endPos = +index + 50
|
||||
// fyi, the + is to let javascript know it's actually a number instead of a string
|
||||
|
||||
if(startPos < 0){
|
||||
startPos = 0
|
||||
}
|
||||
if(endPos >= this.length){
|
||||
endPos = this.length - 1
|
||||
}
|
||||
|
||||
let navigatorItems = document.getElementById("list_navigator").children
|
||||
|
||||
for (let i = startPos; i <= endPos; i++){
|
||||
if (navigatorItems[i].innerHTML.includes("list_item_thumbnail")) {
|
||||
continue // Thumbnail already loaded
|
||||
}
|
||||
|
||||
let thumb = "/api/file/" + this.files[i].id + "/thumbnail?width=48&height=48"
|
||||
let name = this.files[i].name
|
||||
|
||||
let itemHtml = "<img src=\"" + thumb + "\" "
|
||||
+ "class=\"list_item_thumbnail\" alt=\"" + escapeHTML(name) + "\"/>"
|
||||
+ escapeHTML(name)
|
||||
|
||||
navigatorItems[i].innerHTML = itemHtml
|
||||
}
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
function QRCodeWindow(viewer) {
|
||||
this.viewer = viewer
|
||||
this.visible = false
|
||||
this.src = ""
|
||||
this.modal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
() => { this.toggle() },
|
||||
"QR code", "500px", "auto",
|
||||
)
|
||||
|
||||
this.img = document.createElement("img")
|
||||
this.img.style.display = "block"
|
||||
this.img.style.width = "100%"
|
||||
this.modal.setBody(this.img)
|
||||
|
||||
this.btnQRCode = document.getElementById("btn_qr_code")
|
||||
this.btnQRCode.addEventListener("click", () => { this.toggle() })
|
||||
|
||||
this.setFile()
|
||||
}
|
||||
|
||||
QRCodeWindow.prototype.toggle = function () {
|
||||
if (this.visible) {
|
||||
this.modal.close()
|
||||
this.btnQRCode.classList.remove("button_highlight")
|
||||
this.visible = false
|
||||
} else {
|
||||
this.modal.open()
|
||||
this.btnQRCode.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
this.setFile()
|
||||
}
|
||||
}
|
||||
|
||||
QRCodeWindow.prototype.setFile = function () {
|
||||
this.src = "/api/misc/qr?text=" + encodeURIComponent(window.location.href)
|
||||
|
||||
if (this.visible) {
|
||||
this.img.src = this.src
|
||||
}
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
function Skyscraper() {
|
||||
this.visible = false
|
||||
|
||||
this.divSkyscraper = document.getElementById("skyscraper")
|
||||
this.divAdSpace = document.getElementById("skyscraper_ad_space")
|
||||
this.divFilePreview = document.getElementById("filepreview")
|
||||
this.btnClose = document.getElementById("btn_skyscraper_close")
|
||||
this.btnClose.addEventListener("click", () => { this.close() })
|
||||
}
|
||||
|
||||
Skyscraper.prototype.open = function () {
|
||||
// If the ad popup was dismissed less than 24 hours ago we don't show it
|
||||
let dismissal = +localStorage.getItem("viewer_skyscraper_ad_dismissed")
|
||||
let now = new Date().getTime()
|
||||
|
||||
if (dismissal > 0 && now - dismissal < 1000 * 60 * 60 * 24) {
|
||||
console.log("Skyscraper dismissed")
|
||||
return
|
||||
}
|
||||
|
||||
if (skyscraperType === "a-ads") {
|
||||
let adsColours = "&background_color=" + window.style.layer2Color +
|
||||
"&text_color=" + window.style.textColor +
|
||||
"&title_color=" + window.style.highlightColor +
|
||||
"&title_hover_color=" + window.style.highlightColor +
|
||||
"&link_color=" + window.style.highlightColor +
|
||||
"&link_hover_color=" + window.style.highlightColor
|
||||
|
||||
this.divAdSpace.innerHTML = `<iframe
|
||||
data-aa="1811738"
|
||||
src="//ad.a-ads.com/1811738?size=160x600${adsColours}"
|
||||
style="width:160px; height:600px; border:0px; padding:0; overflow:hidden; background-color: transparent;">
|
||||
</iframe>`
|
||||
} else if (skyscraperType === "pixfuture") {
|
||||
|
||||
let div = document.createElement("div")
|
||||
div.id = "27513x160x600x4605x_ADSLOT1"
|
||||
div.setAttribute("clickTrack", "%%CLICK_URL_ESC%%")
|
||||
this.divAdSpace.appendChild(div)
|
||||
|
||||
let script = document.createElement("script")
|
||||
script.async = "async"
|
||||
script.type = "text/javascript"
|
||||
script.src = "https:\/\/served-by.pixfuture.com/www/delivery/headerbid.js"
|
||||
script.setAttribute("slotId", "27513x160x600x4605x_ADSLOT1")
|
||||
script.setAttribute("refreshTime", "5")
|
||||
script.setAttribute("refreshInterval", "60")
|
||||
document.head.appendChild(script)
|
||||
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
this.divSkyscraper.style.right = "0"
|
||||
this.divFilePreview.style.right = this.divSkyscraper.offsetWidth + "px"
|
||||
this.visible = true
|
||||
}
|
||||
|
||||
Skyscraper.prototype.close = function () {
|
||||
this.divSkyscraper.style.right = -this.divSkyscraper.offsetWidth + "px"
|
||||
this.divFilePreview.style.right = "0"
|
||||
this.visible = false
|
||||
|
||||
localStorage.setItem("viewer_skyscraper_ad_dismissed", new Date().getTime())
|
||||
|
||||
// Remove the ad from the DOM to save memory
|
||||
setTimeout(() => { this.divSkyscraper.remove() }, 1000)
|
||||
}
|
@@ -1,205 +0,0 @@
|
||||
function Toolbar(viewer) {
|
||||
this.viewer = viewer
|
||||
this.visible = false
|
||||
this.sharebarVisible = false
|
||||
this.currentFile = null
|
||||
this.editWindow = null
|
||||
|
||||
this.views = 0
|
||||
this.downloads = 0
|
||||
this.statsWebsocket = null
|
||||
|
||||
this.divToolbar = document.getElementById("toolbar")
|
||||
this.divFilePreview = document.getElementById("filepreview")
|
||||
this.downloadFrame = document.getElementById("download_frame")
|
||||
this.spanViews = document.getElementById("stat_views")
|
||||
this.spanDownloads = document.getElementById("stat_downloads")
|
||||
this.spanSize = document.getElementById("stat_size")
|
||||
|
||||
this.btnToggleToolbar = document.getElementById("btn_toggle_toolbar")
|
||||
this.btnDownload = document.getElementById("btn_download")
|
||||
this.btnCopyLink = document.getElementById("btn_copy")
|
||||
this.spanCopyLink = document.querySelector("#btn_copy > span")
|
||||
this.btnShare = document.getElementById("btn_share")
|
||||
this.divSharebar = document.getElementById("sharebar")
|
||||
|
||||
this.btnToggleToolbar.addEventListener("click", () => { this.toggle() })
|
||||
this.btnDownload.addEventListener("click", () => { this.download() })
|
||||
this.btnCopyLink.addEventListener("click", () => { this.copyUrl() })
|
||||
this.btnShare.addEventListener("click", () => { this.toggleSharebar() })
|
||||
}
|
||||
|
||||
Toolbar.prototype.setFile = function (file) {
|
||||
this.currentFile = file
|
||||
this.spanSize.innerText = formatDataVolume(file.size, 3)
|
||||
|
||||
this.setStats()
|
||||
}
|
||||
|
||||
Toolbar.prototype.setStats = function () {
|
||||
let size = this.currentFile.size
|
||||
|
||||
this.spanViews.innerText = "loading..."
|
||||
this.spanDownloads.innerText = "loading..."
|
||||
|
||||
if (this.statsWebsocket !== null) {
|
||||
this.statsWebsocket.close()
|
||||
}
|
||||
|
||||
this.statsWebsocket = new WebSocket(
|
||||
location.origin.replace(/^http/, 'ws') + "/api/file/" + this.currentFile.id + "/stats"
|
||||
)
|
||||
this.statsWebsocket.onmessage = (msg) => {
|
||||
let j = JSON.parse(msg.data)
|
||||
console.debug("WS update", j)
|
||||
|
||||
this.views = j.views
|
||||
this.downloads = Math.round(j.bandwidth / size)
|
||||
this.spanViews.innerText = formatThousands(this.views)
|
||||
this.spanDownloads.innerText = formatThousands(this.downloads)
|
||||
}
|
||||
this.statsWebsocket.onerror = (err) => {
|
||||
console.error("WS error", err)
|
||||
this.statsWebsocket.close()
|
||||
this.statsWebsocket = null
|
||||
|
||||
this.spanViews.innerText = "error"
|
||||
this.spanDownloads.innerText = "retrying..."
|
||||
|
||||
window.setTimeout(() => {
|
||||
if (this.statsWebsocket === null) {
|
||||
this.setStats()
|
||||
}
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
|
||||
Toolbar.prototype.toggle = function () {
|
||||
if (this.visible) {
|
||||
if (this.sharebarVisible) { this.toggleSharebar() }
|
||||
|
||||
this.divToolbar.style.left = "-8em"
|
||||
this.divFilePreview.style.left = "0px"
|
||||
this.btnToggleToolbar.classList.remove("button_highlight")
|
||||
this.visible = false
|
||||
} else {
|
||||
this.divToolbar.style.left = "0px"
|
||||
this.divFilePreview.style.left = "8em"
|
||||
this.btnToggleToolbar.classList.add("button_highlight")
|
||||
this.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
Toolbar.prototype.toggleSharebar = function () {
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: this.viewer.title,
|
||||
text: "Download " + this.viewer.title + " here",
|
||||
url: window.location.href
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (this.sharebarVisible) {
|
||||
this.divSharebar.style.left = "-8em"
|
||||
this.btnShare.classList.remove("button_highlight")
|
||||
this.sharebarVisible = false
|
||||
} else {
|
||||
this.divSharebar.style.left = "8em"
|
||||
this.btnShare.classList.add("button_highlight")
|
||||
this.sharebarVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
Toolbar.prototype.download = function () {
|
||||
if (captchaKey === "none" || captchaKey === "") {
|
||||
console.debug("Server doesn't support captcha, starting download")
|
||||
this.downloadFrame.src = this.currentFile.download_href
|
||||
return
|
||||
}
|
||||
|
||||
if (this.currentFile.availability === "") {
|
||||
console.debug("File is available, starting download")
|
||||
this.downloadFrame.src = this.currentFile.download_href
|
||||
} else {
|
||||
console.debug("File is not readily available, showing captcha dialog")
|
||||
|
||||
let showCaptcha = (title, text) => {
|
||||
// Create the modal
|
||||
this.captchaModal = new Modal(
|
||||
document.getElementById("file_viewer"),
|
||||
null, title, "500px", "auto",
|
||||
)
|
||||
|
||||
// Clone the popup contents and insert them into the popup
|
||||
let clone = document.getElementById("tpl_captcha_popup").content.cloneNode(true)
|
||||
clone.querySelector(".captcha_text").innerText = text
|
||||
recaptchaElement = clone.querySelector(".captcha_popup_captcha")
|
||||
this.captchaModal.setBody(clone)
|
||||
|
||||
// Set the callback function
|
||||
recaptchaCallback = token => {
|
||||
// Download the file using the recaptcha token
|
||||
this.downloadFrame.src = this.currentFile.download_href + "&recaptcha_response=" + token
|
||||
this.captchaModal.close()
|
||||
}
|
||||
|
||||
// Load the recaptcha script with a load function
|
||||
let script = document.createElement("script")
|
||||
script.src = "https://www.google.com/recaptcha/api.js?onload=loadCaptcha&render=explicit"
|
||||
document.body.appendChild(script)
|
||||
|
||||
// Show the popup
|
||||
this.captchaModal.open()
|
||||
}
|
||||
|
||||
console.log(this.currentFile.availability)
|
||||
if (this.currentFile.availability === "file_rate_limited_captcha_required") {
|
||||
console.debug("Showing rate limiting captcha")
|
||||
showCaptcha(
|
||||
"Rate limiting enabled!",
|
||||
"This file is using a suspicious amount of bandwidth relative " +
|
||||
"to its popularity. To continue downloading this file you " +
|
||||
"will have to prove that you're a human first.",
|
||||
)
|
||||
} else if (this.currentFile.availability === "virus_detected_captcha_required") {
|
||||
console.debug("Showing virus captcha")
|
||||
showCaptcha(
|
||||
"Malware warning!",
|
||||
"According to our scanning systems this file may contain a " +
|
||||
"virus of type '" + this.currentFile.availability_name + "'. You " +
|
||||
"can continue downloading this file at your own risk, but you " +
|
||||
"will have to prove that you're a human first.",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Toolbar.prototype.copyUrl = function () {
|
||||
if (copyText(window.location.href)) {
|
||||
console.log('Text copied')
|
||||
this.spanCopyLink.innerText = "Copied!"
|
||||
this.btnCopyLink.classList.add("button_highlight")
|
||||
} else {
|
||||
console.log('Copying not supported')
|
||||
this.spanCopyLink.innerText = "Error!"
|
||||
alert("Your browser does not support copying text.")
|
||||
}
|
||||
|
||||
// Return to normal
|
||||
setTimeout(() => {
|
||||
this.spanCopyLink.innerText = "Copy"
|
||||
this.btnCopyLink.classList.remove("button_highlight")
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
// Called by the google recaptcha script
|
||||
let recaptchaElement = null
|
||||
let recaptchaCallback = null
|
||||
function loadCaptcha() {
|
||||
grecaptcha.render(recaptchaElement, {
|
||||
sitekey: captchaKey,
|
||||
theme: "dark",
|
||||
callback: recaptchaCallback,
|
||||
})
|
||||
}
|
@@ -1,364 +0,0 @@
|
||||
function Viewer(type, viewToken, data) {
|
||||
// Set defaults
|
||||
this.toolbar = null
|
||||
this.listNavigator = null
|
||||
this.detailsWindow = null
|
||||
this.divFilepreview = null
|
||||
this.file = null
|
||||
this.title = "" // Contains either the file name or list title
|
||||
this.listId = ""
|
||||
this.viewToken = viewToken
|
||||
this.isList = false
|
||||
this.isFile = false
|
||||
this.initialized = false
|
||||
this.viewerScript = null
|
||||
this.fullscreen = false
|
||||
|
||||
this.toolbar = new Toolbar(this)
|
||||
this.detailsWindow = new DetailsWindow(this)
|
||||
this.editWindow = new EditWindow()
|
||||
this.qrCodeWindow = new QRCodeWindow(this)
|
||||
this.skyscraper = new Skyscraper()
|
||||
|
||||
this.divFilepreview = document.getElementById("filepreview")
|
||||
|
||||
// On small screens the toolbar takes too much space, so it collapses
|
||||
// automatically
|
||||
if (this.divFilepreview.clientWidth > 600 && !this.toolbar.visible) {
|
||||
this.toolbar.toggle()
|
||||
}
|
||||
if (this.divFilepreview.clientWidth > 800) {
|
||||
this.skyscraper.open()
|
||||
}
|
||||
|
||||
if (embeddedViewer) {
|
||||
// Remove padding from the headerbar
|
||||
document.getElementById("file_viewer_headerbar").classList += " file_viewer_headerbar_embedded"
|
||||
|
||||
// Hide toolbar by default
|
||||
if (this.toolbar.visible) {
|
||||
this.toolbar.toggle()
|
||||
}
|
||||
|
||||
// Alter home button to open in a new tab
|
||||
document.getElementById("button_home").setAttribute("target", "_blank")
|
||||
|
||||
// Remove sponsor bar if ads are disabled
|
||||
if (!data.show_ads) {
|
||||
document.getElementById("sponsors").remove()
|
||||
}
|
||||
|
||||
// Show fullscreen button if this browser supports it
|
||||
if (document.documentElement.requestFullscreen) {
|
||||
let btnFullscreen = document.getElementById("btn_fullscreen")
|
||||
btnFullscreen.style.display = ""
|
||||
btnFullscreen.addEventListener("click", () => { this.toggleFullscreen() })
|
||||
}
|
||||
}
|
||||
|
||||
if (type === "file") {
|
||||
this.isFile = true
|
||||
this.title = data.name
|
||||
this.setFile(fileFromAPIResp(data))
|
||||
} else if (type === "list") {
|
||||
this.isList = true
|
||||
this.listId = data.id
|
||||
this.title = data.title
|
||||
|
||||
let files = []
|
||||
for (let i in data.files) {
|
||||
files.push(fileFromAPIResp(data.files[i]))
|
||||
}
|
||||
this.listNavigator = new ListNavigator(this, files)
|
||||
} else if (type === "skylink") {
|
||||
this.isFile = true
|
||||
this.title = data.name
|
||||
document.getElementById("btn_details").remove()
|
||||
document.getElementById("stat_views_label").remove()
|
||||
document.getElementById("stat_views").remove()
|
||||
document.getElementById("stat_downloads_label").remove()
|
||||
document.getElementById("stat_downloads").remove()
|
||||
this.setFile(fileFromSkyNet(data))
|
||||
}
|
||||
|
||||
this.embedWindow = new EmbedWindow(this)
|
||||
this.abuseReportWindow = new AbuseReportWindow(this)
|
||||
|
||||
if (userAuthenticated && !this.file.can_edit) {
|
||||
let btnGrab = document.getElementById("btn_grab")
|
||||
btnGrab.style.display = ""
|
||||
btnGrab.addEventListener("click", () => { this.grabFile() })
|
||||
}
|
||||
|
||||
this.renderSponsors()
|
||||
window.addEventListener("resize", e => { this.renderSponsors() })
|
||||
|
||||
// Register keyboard shortcuts
|
||||
document.addEventListener("keydown", e => { this.keyboardEvent(e) })
|
||||
|
||||
// Show introduction popup
|
||||
new IntroPopup()
|
||||
|
||||
// Delete all the garbage that advertisers leave behind in my cookies and
|
||||
// localstorage
|
||||
// window.addEventListener("beforeunload", () => {
|
||||
// document.cookie.split("; ").forEach(cookie => {
|
||||
// let name = cookie.split("=")[0]
|
||||
// if (name !== "pd_auth_key" && name !== "style") {
|
||||
// document.cookie = name + "=; Max-Age=0; expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Lax; path=/;"
|
||||
// }
|
||||
// })
|
||||
|
||||
// let keys = []
|
||||
// for (let i = 0; i < localStorage.length; i++) {
|
||||
// keys.push(localStorage.key(i))
|
||||
// }
|
||||
// keys.forEach(key => {
|
||||
// if (key !== "viewer_intro_popup_dismissed" && key !== "uploaded_files") {
|
||||
// localStorage.removeItem(key)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
|
||||
this.initialized = true
|
||||
}
|
||||
|
||||
Viewer.prototype.getFile = function () {
|
||||
return this.file
|
||||
}
|
||||
|
||||
Viewer.prototype.setFile = function (file) {
|
||||
this.file = file
|
||||
|
||||
if (this.isList) {
|
||||
document.getElementById("file_viewer_list_title").innerText = this.title
|
||||
document.getElementById("file_viewer_file_title").innerText = file.name
|
||||
document.title = this.title + " ~ " + file.name + " ~ pixeldrain"
|
||||
} else {
|
||||
document.getElementById("file_viewer_file_title").innerText = file.name
|
||||
document.title = file.name + " ~ pixeldrain"
|
||||
}
|
||||
|
||||
// Relay the file change event to all components
|
||||
this.detailsWindow.setFile(file)
|
||||
this.editWindow.setFile(file)
|
||||
this.toolbar.setFile(file)
|
||||
this.qrCodeWindow.setFile()
|
||||
|
||||
// Register a new view. We don't care what this returns becasue we can't
|
||||
// do anything about it anyway
|
||||
if (file.view_href !== "") {
|
||||
fetch(file.view_href, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: "token=" + this.viewToken
|
||||
})
|
||||
}
|
||||
|
||||
// Clean up the previous viewer if possible
|
||||
if (this.viewerScript !== null && typeof this.viewerScript.destroy === "function") {
|
||||
this.viewerScript.destroy()
|
||||
}
|
||||
|
||||
// Clear the canvas
|
||||
this.divFilepreview.innerHTML = ""
|
||||
|
||||
// This function can be used by the viewer scripts to navigate to the next
|
||||
// file when a songs has ended for example
|
||||
let nextItem = () => {
|
||||
if (this.listNavigator !== null) {
|
||||
this.listNavigator.nextItem()
|
||||
}
|
||||
}
|
||||
|
||||
if (file.abuse_type !== "") {
|
||||
this.viewerScript = new AbuseViewer(this, file)
|
||||
} else if (file.mime_type.startsWith("image")) {
|
||||
this.viewerScript = new ImageViewer(this, file)
|
||||
} else if (
|
||||
file.mime_type.startsWith("video") ||
|
||||
file.mime_type === "application/matroska" ||
|
||||
file.mime_type === "application/x-matroska"
|
||||
) {
|
||||
this.viewerScript = new VideoViewer(this, file, nextItem)
|
||||
} else if (
|
||||
file.mime_type.startsWith("audio") ||
|
||||
file.mime_type === "application/ogg" ||
|
||||
file.name.endsWith(".mp3")
|
||||
) {
|
||||
this.viewerScript = new AudioViewer(this, file, nextItem)
|
||||
} else if (
|
||||
file.mime_type === "application/pdf" ||
|
||||
file.mime_type === "application/x-pdf"
|
||||
) {
|
||||
this.viewerScript = new PDFViewer(this, file)
|
||||
} else if (
|
||||
file.mime_type.startsWith("text") ||
|
||||
file.id === "demo"
|
||||
) {
|
||||
this.viewerScript = new TextViewer(this, file)
|
||||
} else {
|
||||
this.viewerScript = new FileViewer(this, file)
|
||||
}
|
||||
|
||||
this.viewerScript.render(this.divFilepreview)
|
||||
}
|
||||
|
||||
Viewer.prototype.renderSponsors = function () {
|
||||
// Check if the ad is enabled
|
||||
if (document.querySelector(".sponsors_banner") == null) { return }
|
||||
|
||||
let scaleWidth = 1
|
||||
let scaleHeight = 1
|
||||
let minWindowHeight = 800
|
||||
let bannerWidth = document.querySelector(".sponsors_banner").offsetWidth
|
||||
let bannerHeight = document.querySelector(".sponsors_banner").offsetHeight
|
||||
|
||||
if (window.innerWidth < bannerWidth) {
|
||||
scaleWidth = window.innerWidth / bannerWidth
|
||||
}
|
||||
if (window.innerHeight < minWindowHeight) {
|
||||
scaleHeight = window.innerHeight / minWindowHeight
|
||||
}
|
||||
|
||||
// The smaller scale is the scale we'll use
|
||||
let scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight
|
||||
|
||||
// Because of the scale transformation the automatic margins don't work
|
||||
// anymore. So we have to manually calculate the margin. Here we take the
|
||||
// width of the viewport - the width of the ad to calculate the amount of
|
||||
// pixels around the ad. We multiply the ad size by the scale we calculated
|
||||
// to account for the smaller size.
|
||||
let offset = (window.innerWidth - (bannerWidth * scale)) / 2
|
||||
|
||||
document.querySelector(".sponsors").style.height = (bannerHeight * scale) + "px"
|
||||
document.querySelector(".sponsors_banner").style.marginLeft = offset + "px"
|
||||
document.querySelector(".sponsors_banner").style.transform = "scale(" + scale + ")"
|
||||
}
|
||||
|
||||
Viewer.prototype.keyboardEvent = function (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") {
|
||||
return // Prevent shortcuts from interfering with input fields
|
||||
}
|
||||
|
||||
console.debug("Key pressed: " + evt.keyCode)
|
||||
switch (evt.keyCode) {
|
||||
case 65: // A or left arrow key go to previous file
|
||||
case 37:
|
||||
if (this.listNavigator != null) {
|
||||
this.listNavigator.previousItem()
|
||||
}
|
||||
break
|
||||
case 68: // D or right arrow key go to next file
|
||||
case 39:
|
||||
if (this.listNavigator != null) {
|
||||
this.listNavigator.nextItem()
|
||||
}
|
||||
break
|
||||
case 83:
|
||||
if (evt.shiftKey) {
|
||||
this.listNavigator.downloadList() // SHIFT + S downloads all files in list
|
||||
} else {
|
||||
this.toolbar.download() // S to download the current file
|
||||
}
|
||||
break
|
||||
case 82: // R to toggle list shuffle
|
||||
if (this.listNavigator != null) {
|
||||
this.listNavigator.toggleShuffle()
|
||||
}
|
||||
break
|
||||
case 67: // C to copy to clipboard
|
||||
this.toolbar.copyUrl()
|
||||
break
|
||||
case 73: // I to open the details window
|
||||
this.detailsWindow.toggle()
|
||||
break
|
||||
case 69: // E to open the edit window
|
||||
this.editWindow.toggle()
|
||||
break
|
||||
case 77: // M to open the embed window
|
||||
this.embedWindow.toggle()
|
||||
break
|
||||
case 71: // G to grab this file
|
||||
this.grabFile()
|
||||
break
|
||||
case 81: // Q to close the window
|
||||
window.close()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Viewer.prototype.toggleFullscreen = function () {
|
||||
if (!this.fullscreen) {
|
||||
document.documentElement.requestFullscreen()
|
||||
document.getElementById("btn_fullscreen_icon").innerText = "fullscreen_exit"
|
||||
this.fullscreen = true
|
||||
} else {
|
||||
document.exitFullscreen()
|
||||
document.getElementById("btn_fullscreen_icon").innerText = "fullscreen"
|
||||
this.fullscreen = false
|
||||
}
|
||||
}
|
||||
|
||||
Viewer.prototype.grabFile = async function () {
|
||||
if (!userAuthenticated || this.file.can_edit) {
|
||||
return
|
||||
}
|
||||
|
||||
const form = new FormData()
|
||||
form.append("grab_file", this.file.id)
|
||||
console.log(this.file.id)
|
||||
|
||||
try {
|
||||
const resp = await fetch(apiEndpoint + "/file", { method: "POST", body: form });
|
||||
if (resp.status >= 400) {
|
||||
throw (await resp.json()).message
|
||||
}
|
||||
|
||||
window.open(domainURL() + "/u/" + (await resp.json()).id, "_blank")
|
||||
} catch (err) {
|
||||
alert("Failed to grab file: " + err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Against XSS attacks
|
||||
function escapeHTML(str) {
|
||||
return String(str)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
function fileFromAPIResp(resp) {
|
||||
resp.date_created = new Date(resp.date_upload)
|
||||
resp.date_last_view = new Date(resp.date_last_view)
|
||||
resp.icon_href = apiEndpoint + "/file/" + resp.id + "/thumbnail"
|
||||
resp.get_href = apiEndpoint + "/file/" + resp.id
|
||||
resp.download_href = apiEndpoint + "/file/" + resp.id + "?download"
|
||||
resp.view_href = apiEndpoint + "/file/" + resp.id + "/view"
|
||||
resp.timeseries_href = apiEndpoint + "/file/" + resp.id + "/timeseries"
|
||||
resp.stats_href = apiEndpoint + "/file/" + resp.id + "/stats"
|
||||
resp.link = domainURL() + "/u/" + resp.id
|
||||
if (resp.description === undefined) {
|
||||
resp.description = ""
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
function fileFromSkyNet(resp) {
|
||||
let file = fileFromAPIResp(resp)
|
||||
file.icon_href = "/res/img/mime/empty.png"
|
||||
file.get_href = "https://siasky.net/file/" + resp.id
|
||||
file.download_href = "https://siasky.net/file/" + resp.id + "?attachment=1"
|
||||
file.view_href = ""
|
||||
file.timeseries_href = ""
|
||||
file.stats_href = ""
|
||||
file.link = domainURL() + "/s/" + resp.id
|
||||
return file
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
function AbuseViewer(viewer, file, next) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
this.next = next
|
||||
|
||||
this.container = document.createElement("div")
|
||||
this.container.classList = "image-container"
|
||||
this.container.appendChild(document.createElement("br"))
|
||||
|
||||
this.title = document.createElement("h1")
|
||||
this.title.innerText = "Unavailable For Legal Reasons"
|
||||
this.container.appendChild(this.title)
|
||||
|
||||
this.description = document.createElement("p")
|
||||
this.description.innerText = "This file has received an abuse report and " +
|
||||
"was taken down."
|
||||
this.container.appendChild(this.description)
|
||||
|
||||
this.description2 = document.createElement("p")
|
||||
this.description2.innerText = "Type of abuse: " + file.abuse_type + ". " +
|
||||
"Reporter: " + file.abuse_reporter_name + "."
|
||||
this.container.appendChild(this.description2)
|
||||
}
|
||||
|
||||
AbuseViewer.prototype.render = function (parent) {
|
||||
parent.appendChild(this.container)
|
||||
|
||||
// Disable the download button
|
||||
this.btnDownloadDisplay = this.viewer.toolbar.btnDownload.style.display
|
||||
this.viewer.toolbar.btnDownload.style.display = "none"
|
||||
}
|
||||
|
||||
AbuseViewer.prototype.destroy = function (parent) {
|
||||
// Restore the download button
|
||||
this.viewer.toolbar.btnDownload.style.display = this.btnDownloadDisplay
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
function AudioViewer(viewer, file, next) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
this.next = next
|
||||
|
||||
this.container = document.createElement("div")
|
||||
this.container.classList = "image-container"
|
||||
this.container.appendChild(document.createElement("br"))
|
||||
|
||||
this.icon = document.createElement("img")
|
||||
this.icon.src = "/api/file/" + this.file.id + "/thumbnail"
|
||||
this.container.appendChild(this.icon)
|
||||
|
||||
this.container.appendChild(document.createElement("br"))
|
||||
this.container.appendChild(document.createTextNode(this.file.name))
|
||||
this.container.appendChild(document.createElement("br"))
|
||||
this.container.appendChild(document.createElement("br"))
|
||||
|
||||
this.element = document.createElement("audio")
|
||||
this.element.controls = "controls"
|
||||
this.element.style.width = "90%"
|
||||
this.element.addEventListener("ended", () => { this.next() }, false)
|
||||
if (!embeddedViewer) {
|
||||
this.element.autoplay = "autoplay"
|
||||
}
|
||||
|
||||
this.source = document.createElement("source")
|
||||
this.source.src = this.file.get_href
|
||||
this.element.appendChild(this.source)
|
||||
this.container.appendChild(this.element)
|
||||
}
|
||||
|
||||
AudioViewer.prototype.render = function (parent) {
|
||||
parent.appendChild(this.container)
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
function FileViewer(viewer, file, next) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
this.next = next
|
||||
|
||||
this.container = document.createElement("div")
|
||||
this.container.classList = "image-container"
|
||||
this.container.appendChild(document.createElement("br"))
|
||||
|
||||
this.title = document.createElement("h1")
|
||||
this.title.innerText = "You are viewing a file on pixeldrain"
|
||||
this.container.appendChild(this.title)
|
||||
|
||||
this.icon = document.createElement("img")
|
||||
this.icon.style.display = "inline-block"
|
||||
this.icon.style.verticalAlign = "middle"
|
||||
this.icon.src = this.file.icon_href
|
||||
this.container.appendChild(this.icon)
|
||||
|
||||
this.fileDetails = document.createElement("div")
|
||||
this.fileDetails.style.display = "inline-block"
|
||||
this.fileDetails.style.textAlign = "left"
|
||||
this.fileDetails.style.paddingLeft = "8px"
|
||||
this.fileDetails.style.verticalAlign = "middle"
|
||||
|
||||
this.fileDetails.appendChild(document.createTextNode("Name: " + file.name))
|
||||
this.fileDetails.appendChild(document.createElement("br"))
|
||||
this.fileDetails.appendChild(document.createTextNode("Type: " + file.mime_type))
|
||||
this.fileDetails.appendChild(document.createElement("br"))
|
||||
this.fileDetails.appendChild(document.createTextNode(
|
||||
"No preview is available for this file type. Download to view it locally"
|
||||
))
|
||||
this.fileDetails.appendChild(document.createElement("br"))
|
||||
|
||||
this.btnDL = document.createElement("button")
|
||||
this.btnDL.addEventListener("click", () => { viewer.toolbar.download() })
|
||||
this.btnDL.innerHTML = `<i class="icon">save</i> Download`
|
||||
this.btnDL.classList = "button_highlight"
|
||||
this.fileDetails.appendChild(this.btnDL)
|
||||
|
||||
this.container.appendChild(this.fileDetails)
|
||||
}
|
||||
|
||||
FileViewer.prototype.render = function (parent) {
|
||||
parent.appendChild(this.container)
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
function ImageViewer(viewer, file) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
this.zoomed = false
|
||||
this.x = 0
|
||||
this.y = 0
|
||||
this.dragging = false
|
||||
|
||||
this.zoom = 1
|
||||
|
||||
this.container = document.createElement("dv")
|
||||
this.container.classList = "image-container"
|
||||
|
||||
this.element = document.createElement("img")
|
||||
this.element.classList = "pannable center drop_shadow"
|
||||
this.element.src = this.file.get_href
|
||||
this.element.addEventListener("dblclick", (e) => { return this.doubleclick(e) })
|
||||
this.element.addEventListener("doubletap", (e) => { return this.doubleclick(e) })
|
||||
this.element.addEventListener("mousedown", (e) => { return this.mousedown(e) })
|
||||
this.element.addEventListener("mousedown", (e) => { return this.mousedown(e) })
|
||||
// this.element.addEventListener("wheel", (e) => { return this.scroll(e) })
|
||||
document.addEventListener("mousemove", (e) => { return this.mousemove(e) })
|
||||
document.addEventListener("mouseup", (e) => { return this.mouseup(e) })
|
||||
|
||||
this.container.appendChild(this.element)
|
||||
}
|
||||
|
||||
ImageViewer.prototype.render = function(parent) {
|
||||
parent.appendChild(this.container)
|
||||
}
|
||||
|
||||
ImageViewer.prototype.scroll = function(e) {
|
||||
if (!this.zoomed) {
|
||||
this.doubleclick(e)
|
||||
}
|
||||
|
||||
console.log(e.deltaY)
|
||||
|
||||
this.zoom = this.zoom - (e.deltaY * 0.01);
|
||||
if (this.zoom < 1) { this.zoom = 1 }
|
||||
if (this.zoom > 10) { this.zoom = 10 }
|
||||
|
||||
this.element.style.width = this.zoom * 100 + "%"
|
||||
this.element.style.height = "auto"
|
||||
this.element.style.maxWidth = "1000%"
|
||||
this.element.style.maxHeight = "1000%"
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
|
||||
ImageViewer.prototype.doubleclick = function(e) {
|
||||
if (this.zoomed) {
|
||||
this.element.removeAttribute("style")
|
||||
this.container.style.overflow = ""
|
||||
this.zoomed = false
|
||||
} else {
|
||||
this.element.style.maxWidth = "none"
|
||||
this.element.style.maxHeight = "none"
|
||||
this.element.style.top = "0"
|
||||
this.element.style.left = ""
|
||||
this.element.style.transform = "none"
|
||||
this.container.style.overflow = "scroll"
|
||||
this.zoomed = true
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
|
||||
ImageViewer.prototype.mousedown = function(e) {
|
||||
if (!this.dragging && e.which === 1 && this.zoomed) {
|
||||
this.x = e.pageX
|
||||
this.y = e.pageY
|
||||
this.dragging = true
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
ImageViewer.prototype.mousemove = function(e) {
|
||||
if (this.dragging) {
|
||||
this.container.scrollLeft = this.container.scrollLeft - (e.pageX - this.x)
|
||||
this.container.scrollTop = this.container.scrollTop - (e.pageY - this.y)
|
||||
|
||||
this.x = e.pageX
|
||||
this.y = e.pageY
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
ImageViewer.prototype.mouseup = function(e) {
|
||||
if (this.dragging) {
|
||||
this.dragging = false
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
function PDFViewer(viewer, file) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
|
||||
this.container = document.createElement("iframe")
|
||||
this.container.classList = "image-container"
|
||||
this.container.style.border = "none"
|
||||
this.container.src = "/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(this.file.get_href)
|
||||
}
|
||||
PDFViewer.prototype.render = function(parent) {
|
||||
parent.appendChild(this.container)
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
function TextViewer(viewer, file) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
this.pre = null
|
||||
this.prettyprint = null
|
||||
|
||||
this.container = document.createElement("div")
|
||||
this.container.classList = "text-container"
|
||||
|
||||
if (this.file.name.endsWith(".md") || this.file.name.endsWith(".markdown") || file.mime_type === "text/demo") {
|
||||
this.getMarkdown()
|
||||
} else if (this.file.name.endsWith(".txt")) {
|
||||
this.getText()
|
||||
} else {
|
||||
this.getCode()
|
||||
}
|
||||
}
|
||||
|
||||
TextViewer.prototype.getCode = function () {
|
||||
this.pre = document.createElement("pre")
|
||||
this.pre.classList = "pre-container prettyprint linenums"
|
||||
this.pre.innerText = "Loading..."
|
||||
this.container.appendChild(this.pre)
|
||||
|
||||
if (this.file.size > 1 << 20) { // File larger than 1 MiB
|
||||
this.pre.innerText = "File is too large to view online.\nPlease download and view it locally."
|
||||
return
|
||||
}
|
||||
|
||||
fetch(this.file.get_href).then(resp => {
|
||||
if (!resp.ok) { return Promise.reject(resp.status) }
|
||||
return resp.text()
|
||||
}).then(resp => {
|
||||
this.pre.innerText = resp
|
||||
|
||||
// Load prettyprint script
|
||||
this.prettyprint = document.createElement("script")
|
||||
this.prettyprint.src = `{{noescape "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert"}}`
|
||||
this.container.appendChild(this.prettyprint)
|
||||
}).catch(err => {
|
||||
this.pre.innerText = "Error loading file: " + err
|
||||
})
|
||||
}
|
||||
|
||||
TextViewer.prototype.getText = function () {
|
||||
this.pre = document.createElement("pre")
|
||||
this.pre.innerText = "Loading..."
|
||||
this.container.appendChild(this.pre)
|
||||
|
||||
if (this.file.size > 1 << 20) { // File larger than 1 MiB
|
||||
this.pre.innerText = "File is too large to view online.\nPlease download and view it locally."
|
||||
return
|
||||
}
|
||||
|
||||
fetch(this.file.get_href).then(resp => {
|
||||
if (!resp.ok) { return Promise.reject(resp.status) }
|
||||
return resp.text()
|
||||
}).then(resp => {
|
||||
this.pre.innerText = resp
|
||||
}).catch(err => {
|
||||
this.pre.innerText = "Error loading file: " + err
|
||||
})
|
||||
}
|
||||
|
||||
TextViewer.prototype.getMarkdown = function () {
|
||||
fetch(
|
||||
domainURL() + window.location.pathname + "/preview"
|
||||
).then(resp => {
|
||||
if (!resp.ok) { return Promise.reject(resp.status) }
|
||||
return resp.text()
|
||||
}).then(resp => {
|
||||
this.container.innerHTML = resp
|
||||
}).catch(err => {
|
||||
this.container.innerText = "Error loading file: " + err
|
||||
})
|
||||
}
|
||||
|
||||
TextViewer.prototype.render = function (parent) {
|
||||
parent.appendChild(this.container)
|
||||
}
|
@@ -1,75 +0,0 @@
|
||||
function VideoViewer(viewer, file, next) {
|
||||
this.viewer = viewer
|
||||
this.file = file
|
||||
this.next = next
|
||||
}
|
||||
|
||||
VideoViewer.prototype.render = function (parent) {
|
||||
if (this.file.allow_video_player) {
|
||||
let vidContainer = document.createElement("div")
|
||||
vidContainer.classList = "image-container"
|
||||
|
||||
let vidElement = document.createElement("video")
|
||||
vidElement.controls = "controls"
|
||||
vidElement.playsInline = "playsInline"
|
||||
vidElement.classList = "center drop_shadow"
|
||||
vidElement.addEventListener("ended", () => { this.next() }, false)
|
||||
if (!embeddedViewer) {
|
||||
vidElement.autoplay = "autoplay"
|
||||
}
|
||||
|
||||
let videoSource = document.createElement("source")
|
||||
videoSource.src = this.file.get_href
|
||||
videoSource.type = this.file.mime_type
|
||||
|
||||
vidElement.appendChild(videoSource)
|
||||
vidContainer.appendChild(vidElement)
|
||||
parent.appendChild(vidContainer)
|
||||
|
||||
// Possible fix for ios 15 video bug?
|
||||
videoSource.src = this.file.get_href
|
||||
videoSource.type = this.file.mime_type
|
||||
} else {
|
||||
let container = document.createElement("div")
|
||||
container.classList = "image-container"
|
||||
container.appendChild(document.createElement("br"))
|
||||
|
||||
let title = document.createElement("h1")
|
||||
title.innerText = "This is a video file on pixeldrain"
|
||||
container.appendChild(title)
|
||||
|
||||
let icon = document.createElement("img")
|
||||
icon.style.display = "inline-block"
|
||||
icon.style.verticalAlign = "middle"
|
||||
icon.src = this.file.icon_href
|
||||
container.appendChild(icon)
|
||||
|
||||
let fileDetails = document.createElement("div")
|
||||
fileDetails.style.display = "inline-block"
|
||||
fileDetails.style.textAlign = "left"
|
||||
fileDetails.style.paddingLeft = "8px"
|
||||
fileDetails.style.verticalAlign = "middle"
|
||||
fileDetails.style.maxWidth = "600px"
|
||||
|
||||
fileDetails.appendChild(document.createTextNode(
|
||||
`The online video player on pixeldrain has been disabled due to
|
||||
repeated abuse. You can still watch videos online by upgrading to
|
||||
Pro. Or download the video and watch it locally on your computer.`,
|
||||
))
|
||||
fileDetails.appendChild(document.createElement("br"))
|
||||
|
||||
let upgradeBtn = document.createElement("a")
|
||||
upgradeBtn.innerHTML = `<i class="icon">upgrade</i> Upgrade to Pro`
|
||||
upgradeBtn.classList = "button button_highlight"
|
||||
upgradeBtn.href = `{{noescape "https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12"}}`
|
||||
fileDetails.appendChild(upgradeBtn)
|
||||
|
||||
let downloadBtn = document.createElement("button")
|
||||
downloadBtn.innerHTML = `<i class="icon">save</i> Download`
|
||||
downloadBtn.addEventListener("click", () => { this.viewer.toolbar.download() })
|
||||
fileDetails.appendChild(downloadBtn)
|
||||
|
||||
container.appendChild(fileDetails)
|
||||
parent.appendChild(container)
|
||||
}
|
||||
}
|
@@ -1,155 +0,0 @@
|
||||
#page_body {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Override the menu button so it doesn't overlap the file manager when the menu
|
||||
is collapsed */
|
||||
#button_toggle_navigation {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file_manager {
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
background-color: var(--layer_2_color);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.file_manager > .nav_bar {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.file_manager > .nav_bar > button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.file_manager > .nav_bar > .spacer {width: 8px;}
|
||||
.file_manager > .nav_bar > .breadcrumbs {
|
||||
flex-grow: .7;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.file_manager > .nav_bar > .input_search {
|
||||
flex-grow: .3;
|
||||
flex-shrink: 1;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.file_manager > .directory_area > .directory_sorters {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: sticky;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
background-color: var(--layer_2_color);
|
||||
min-width: 850px;
|
||||
}
|
||||
.file_manager > .directory_area > .directory_sorters > div {
|
||||
display: inline-block;
|
||||
margin: 4px 10px;
|
||||
padding: 4px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid var(--input_color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file_manager > .directory_area > .directory_sorters > :first-child,
|
||||
.node > :first-child {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.file_manager > .directory_area > .directory_sorters > :not(:first-child),
|
||||
.node > :not(:first-child) {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.file_manager > .directory_area {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-x: auto;
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.file_manager > .directory_area > .directory_node_container {
|
||||
/* Required because we use padding for moving the nodes down when items
|
||||
above are out of view*/
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
min-width: 850px;
|
||||
}
|
||||
|
||||
.file_manager > .status_bar {
|
||||
flex-shrink: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.node {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
position: relative;
|
||||
height: 40px;
|
||||
overflow: hidden;
|
||||
|
||||
/* I use padding instead of margin here because it goves me more precise
|
||||
control over the size.
|
||||
Check out https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing*/
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
color: var(--text_color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.node:hover:not(.node_selected) {
|
||||
background-color: var(--input_color_dark);
|
||||
color: var(--input_text_color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.node_selected {
|
||||
background-color: var(--highlight_color);
|
||||
color: var(--highlight_text_color);
|
||||
}
|
||||
.node > div {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: auto 10px;
|
||||
padding: 4px;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.node > div > span {
|
||||
margin: auto;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.node > div > img {
|
||||
max-height: 100%;
|
||||
margin-right: 6px;
|
||||
width: auto;
|
||||
min-width: auto;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
position: absolute;
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
@@ -1,350 +0,0 @@
|
||||
/*
|
||||
Created on : May 22, 2015, 1:20:02 PM
|
||||
Author : Fornax
|
||||
*/
|
||||
|
||||
/* Viewer container */
|
||||
.file_viewer {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
background-color: var(--layer_2_color);
|
||||
}
|
||||
|
||||
/* Headerbar (row 1) */
|
||||
.file_viewer > .file_viewer_headerbar {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
z-index: 10;
|
||||
box-shadow: none;
|
||||
padding: 4px;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar_embedded {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* Headerbar components */
|
||||
.file_viewer > .file_viewer_headerbar > * {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
display: inline;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .file_viewer_headerbar_title {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
line-height: 1.2em; /* When the page is a list there will be two lines. Dont's want to stretch the container*/
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
justify-content: center;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .button_toggle_toolbar > .icon {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .button_home > svg {
|
||||
height: 1.6em;
|
||||
width: 1.6em;
|
||||
margin: 0;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .button_home::after {
|
||||
content: "pixeldrain";
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.file_viewer > .file_viewer_headerbar > .button_home::after {
|
||||
content: "pd";
|
||||
}
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .file_viewer_headerbar_title > span {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
margin-right: 1em;
|
||||
}
|
||||
/* List Navigator (row 2) */
|
||||
.file_viewer > .list_navigator {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
display: none; /* Becomes visible if the page is a list */
|
||||
width: 100%;
|
||||
border-top: 1px solid var(--layer_2_color_border);
|
||||
text-align: center;
|
||||
line-height: 1em;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
z-index: 50;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.file_viewer > .list_navigator > .list_item {
|
||||
height: 2.6em !important;
|
||||
width: 220px !important;
|
||||
}
|
||||
|
||||
/* File preview area (row 3) */
|
||||
.file_viewer > .file_viewer_window {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
z-index: 9;
|
||||
}
|
||||
.file_viewer > .file_viewer_window > .file_viewer_file_preview {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: inline-block;
|
||||
min-height: 100px;
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
transition: left 0.5s, right 0.5s;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 2px 2px 10px 2px var(--shadow_color);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
/* Sponsors (row 4) */
|
||||
.file_viewer > .sponsors {
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
.file_viewer > .sponsors > .sponsors_banner {
|
||||
display: block;
|
||||
margin: auto;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
/* Pop-up warning (row 5) */
|
||||
.file_viewer > .popup_warn {
|
||||
background-color: var(--layer_1_color);
|
||||
border-top: 1px solid var(--layer_1_color_border);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Toolbars */
|
||||
.file_viewer > .file_viewer_window > .file_viewer_toolbar {
|
||||
position: absolute;
|
||||
width: 8em;
|
||||
z-index: 49;
|
||||
overflow: hidden;
|
||||
left: -9em;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
transition: left 0.5s;
|
||||
background-color: var(--layer_2_color);
|
||||
}
|
||||
.file_viewer > .file_viewer_window > .file_viewer_sharebar {
|
||||
position: absolute;
|
||||
width: 7em;
|
||||
left: -8em;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
box-shadow: inset 1px 1px 5px var(--shadow_color);
|
||||
background-color: var(--layer_1_color);
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
z-index: 48;
|
||||
overflow: hidden;
|
||||
transition: left 0.5s;
|
||||
}
|
||||
.file_viewer > .file_viewer_window > .skyscraper {
|
||||
position: absolute;
|
||||
width: 160px;
|
||||
z-index: 49;
|
||||
overflow: hidden;
|
||||
right: -170px;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
transition: right 0.5s;
|
||||
background-color: var(--layer_2_color);
|
||||
}
|
||||
.file_viewer > .file_viewer_window > .skyscraper > .skyscraper_ad_space {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
/* =====================
|
||||
== FILE CONTAINERS ==
|
||||
=====================*/
|
||||
.image-container{
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.text-container{
|
||||
background: #333 none;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.5em;
|
||||
padding: 5px 5px 5px 20px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.text-container > pre {
|
||||
white-space: pre-wrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.center{
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.pannable { cursor: move; }
|
||||
.drop_shadow { box-shadow: 1px 1px 5px var(--shadow_color); }
|
||||
|
||||
/* ========================
|
||||
|| TOOLBAR COMPONENTS ||
|
||||
======================== */
|
||||
|
||||
|
||||
/* Workaround to hide the scrollbar in non webkit browsers, it's really ugly' */
|
||||
.file_viewer_toolbar > div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: -30px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.file_viewer_toolbar > div > div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 8em;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toolbar_button{
|
||||
text-align: left;
|
||||
}
|
||||
.toolbar_button > img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.toolbar_button > span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.toolbar_label {
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
font-size: 0.8em;
|
||||
line-height: 0.7em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
|| SHAREBAR COMPONENTS ||
|
||||
========================= */
|
||||
|
||||
.sharebar-button {text-align: center;}
|
||||
.sharebar-button > svg,
|
||||
.sharebar-button > img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
/* =====================
|
||||
|| MISC COMPONENTS ||
|
||||
===================== */
|
||||
|
||||
.captcha_popup_captcha > div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
table {width: auto !important;}
|
||||
|
||||
/* Abuse report label*/
|
||||
.abuse_type_form > label {
|
||||
display: block;
|
||||
border-bottom: 1px var(--layer_2_color_border) solid;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.abuse_type_form > label:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
/* ====================
|
||||
|| LIST NAVIGATOR ||
|
||||
==================== */
|
||||
|
||||
.file-container{
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.file-container-frame{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.intro_popup {
|
||||
position: absolute;
|
||||
width: 380px;
|
||||
max-width: 80%;
|
||||
height: auto;
|
||||
background-color: var(--layer_4_color);
|
||||
box-shadow: 1px 1px 10px var(--shadow_color);
|
||||
border-radius: 20px;
|
||||
z-index: 50;
|
||||
transition: opacity .4s, left .5s, top .5s;
|
||||
}
|
||||
.intro_popup:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
top: -15px;
|
||||
border-bottom: 15px solid var(--layer_4_color);
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
{{ define "ad_headers" }}
|
||||
{{ if eq .Other.AdBannerType 3 }}
|
||||
<!-- Adshares -->
|
||||
<script type="text/javascript">
|
||||
!function(n){var t,e=function(n,t){var e=[["a","e","i","o","u","y"],["b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"]];if(t)for(var r=0;r<=t.length-1;r++)n=n*t.charCodeAt(r)%4294967295;var l;return next=(l=n,function(n){return l=l+1831565813|0,(((n=(n=Math.imul(l^l>>>15,1|l))+Math.imul(n^n>>>7,61|n)^n)^n>>>14)>>>0)/Math.pow(2,32)}),function(n,t){for(var r=[],l=null,o=0;o<=n-1;o++){var a=void 0;null===l?a=e[0].concat(e[1]):1==l?(a=e[0],l=0):(a=e[1],l=1);var u=a[Math.floor(next()*a.length)];r.push(u),null===l&&(l=-1!=e[0].indexOf(u)?0:1)}return r.push("."+t),r.join("")}}((t=new Date,(t/=1e3)-t%1209600),"_fa7cdd4c68507744")(8,"xyz");if(null===n)console.log("https://"+e);else{var r=n.createElement("script");r.src="https://"+e+"/main.js",(n.body||n.head).appendChild(r)}}("undefined"!=typeof document?document:null);
|
||||
</script>
|
||||
@@ -8,6 +9,7 @@
|
||||
|
||||
{{ define "banner_ads"}}
|
||||
{{ if eq .Other.AdBannerType 1 }}
|
||||
<!-- A-ads -->
|
||||
<!-- scrolling="no" is not allowed by the W3C, but overflow: hidden doesn't work in chrome, so I have no choice -->
|
||||
<iframe class="sponsors_banner"
|
||||
data-aa="73974"
|
||||
@@ -44,6 +46,7 @@
|
||||
<img src="/res/img/misc/banner_amarula_jobs.png" style="width: 100%; height: 100%" />
|
||||
</a>
|
||||
{{ else if eq .Other.AdBannerType 6 }}
|
||||
<!-- Adsterra -->
|
||||
<div class="sponsors_banner" style="display: inline-block; width: 728px; height: 90px;">
|
||||
<script type="text/javascript">
|
||||
atOptions = {
|
||||
@@ -57,10 +60,12 @@
|
||||
</script>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 7 }}
|
||||
<!-- Brave -->
|
||||
<a class="sponsors_banner" style="display: inline-block; width: 728px; height: 90px;" href="/click/MdUXxSov?target=https%3A%2F%2Fbrave.com%2Fpix009">
|
||||
<img src="/res/img/misc/brave-728x90.png" style="width: 100%; height: 100%" />
|
||||
</a>
|
||||
{{ else if eq .Other.AdBannerType 8 }}
|
||||
<!-- Pro ad 1 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<img src="/res/img/pixeldrain_128.png" style="height: 2.4em; vertical-align: middle; margin: 4px;"/>
|
||||
<div style="margin: 4px; display: inline-block; vertical-align: middle;">
|
||||
@@ -69,6 +74,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 9 }}
|
||||
<!-- Pro ad 2 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<img src="/res/img/pixeldrain_128.png" style="height: 2.4em; vertical-align: middle; margin: 4px;"/>
|
||||
<div style="margin: 4px; display: inline-block; vertical-align: middle;">
|
||||
@@ -77,6 +83,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 10 }}
|
||||
<!-- Pro ad 3 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<img src="/res/img/pixeldrain_128.png" style="height: 2.4em; vertical-align: middle; margin: 4px;"/>
|
||||
<div style="margin: 4px; display: inline-block; vertical-align: middle;">
|
||||
@@ -85,6 +92,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 11 }}
|
||||
<!-- Pro ad 4 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<img src="/res/img/pixeldrain_128.png" style="height: 2.4em; vertical-align: middle; margin: 4px;"/>
|
||||
<div style="margin: 4px; display: inline-block; vertical-align: middle;">
|
||||
@@ -117,11 +125,13 @@
|
||||
</script>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 15 }}
|
||||
<!-- Pixfuture -->
|
||||
<!-- AuctionX Display platform tag START -->
|
||||
<div id="27517x728x90x4605x_ADSLOT1" clickTrack="%%CLICK_URL_ESC%%" style="display: block; margin: auto;"></div>
|
||||
<script type="text/javascript" async src="https://served-by.pixfuture.com/www/delivery/headerbid.js" slotId="27517x728x90x4605x_ADSLOT1" refreshTime="5" refreshInterval="60"></script>
|
||||
<!-- AuctionX Display platform tag END -->
|
||||
{{ else if eq .Other.AdBannerType 16 }}
|
||||
<!-- Publisherrest ad 1 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<a href="https://pixeldrain.com/vouchercodes/" class="button button_highlight" style="margin: 8px;">
|
||||
<i class="icon">shopping_cart</i>
|
||||
@@ -130,6 +140,7 @@
|
||||
</a>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 17 }}
|
||||
<!-- Publisherrest ad 2 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<a href="https://pixeldrain.com/vouchercodes/" class="button button_highlight" style="margin: 8px;">
|
||||
<i class="icon">shopping_cart</i>
|
||||
@@ -138,6 +149,7 @@
|
||||
</a>
|
||||
</div>
|
||||
{{ else if eq .Other.AdBannerType 18 }}
|
||||
<!-- Publisherrest ad 3 -->
|
||||
<div style="text-align: center; line-height: 1.4em; font-size: 22px;">
|
||||
<a href="https://pixeldrain.com/vouchercodes/" class="button button_highlight" style="margin: 8px;">
|
||||
<i class="icon">shopping_cart</i>
|
||||
@@ -147,34 +159,3 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "floating_ads"}}
|
||||
{{ if eq .Other.AdFloaterType 3 }}
|
||||
<!-- AdMaven -->
|
||||
<script data-cfasync="false" async src="//d227cncaprzd7y.cloudfront.net/?acncd=905608"></script>
|
||||
{{ else if eq .Other.AdFloaterType 2 }}
|
||||
<!-- AdSterra -->
|
||||
<script type='text/javascript' async src='//concoursestrickenpuppy.com/4c/4d/90/4c4d90a2e79b0e049f811a663f3e3c07.js'></script>
|
||||
{{ else if eq .Other.AdFloaterType 1 }}
|
||||
<!-- PropellerAds -->
|
||||
<script type="text/javascript" src="//optyruntchan.com/400/4189877" data-cfasync="false" async="async"></script>
|
||||
</script>
|
||||
{{ end }}
|
||||
|
||||
{{ if eq .Other.AdPopupType 1 }}
|
||||
<script data-cfasync="false" type="text/javascript" async src="//depirsmandk5.com/t/9/fret/meow4/1846775/brt.js"></script>
|
||||
{{ else if eq .Other.AdPopupType 2 }}
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
(function(s,u,z,p){
|
||||
s.src=u,s.setAttribute('data-zone',z),p.appendChild(s);
|
||||
})(
|
||||
document.createElement('script'),
|
||||
'https://iclickcdn.com/tag.min.js',
|
||||
3750089,
|
||||
document.body||document.documentElement,
|
||||
)
|
||||
})
|
||||
</script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
@@ -1,370 +0,0 @@
|
||||
{{define "file_viewer"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{.Title}}</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
{{ template "opengraph" .OGData }}
|
||||
|
||||
{{ template "user_style" . }}
|
||||
{{ template "user_style_js" . }}
|
||||
|
||||
<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" />
|
||||
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain_180.png" />
|
||||
<link rel="icon" sizes="192x192" href="/res/img/pixeldrain_192.png" />
|
||||
<link rel="icon" sizes="196x196" href="/res/img/pixeldrain_196.png" />
|
||||
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_256.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/res/img/pixeldrain_152.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/res/img/pixeldrain_180.png" />
|
||||
<link rel="shortcut icon" sizes="196x196" href="/res/img/pixeldrain_196.png" />
|
||||
<meta name="theme-color" content="#220735"/>
|
||||
|
||||
<style>
|
||||
{{ template `viewer.css` }}
|
||||
{{ template `modal.css` }}
|
||||
</style>
|
||||
|
||||
{{ template `ad_headers` . }}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="file_viewer" class="file_viewer">
|
||||
<div id="file_viewer_headerbar" class="file_viewer_headerbar">
|
||||
<button id="btn_toggle_toolbar" class="button_toggle_toolbar round">
|
||||
<i class="icon">menu</i>
|
||||
</button>
|
||||
<a href="/" id="button_home" class="button button_home round">
|
||||
{{template `pixeldrain.svg` .}}
|
||||
</a>
|
||||
<div id="file_viewer_headerbar_title" class="file_viewer_headerbar_title">
|
||||
<div id="file_viewer_list_title"></div>
|
||||
<div id="file_viewer_file_title">loading...</div>
|
||||
</div>
|
||||
<!-- fullscreen button becomes visible on embedded viewer -->
|
||||
<button id="btn_fullscreen" class="btn_fullscreen round" style="display: none;">
|
||||
<i class="icon" id="btn_fullscreen_icon">fullscreen</i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="list_navigator" class="list_navigator"></div>
|
||||
<div id="file_viewer_window" class="file_viewer_window">
|
||||
<div id="toolbar" class="file_viewer_toolbar"><div><div>
|
||||
<div id="stat_views_label" class="toolbar_label">Views</div>
|
||||
<div id="stat_views" style="text-align: center;">N/A</div>
|
||||
<div id="stat_downloads_label" class="toolbar_label">Downloads</div>
|
||||
<div id="stat_downloads" style="text-align: center;">N/A</div>
|
||||
<div id="stat_size_label" class="toolbar_label">Size</div>
|
||||
<div id="stat_size" style="text-align: center;">N/A</div>
|
||||
|
||||
<hr/>
|
||||
<button id="btn_download" class="toolbar_button button_full_width">
|
||||
<i class="icon">save</i>
|
||||
<span>Download</span>
|
||||
</button>
|
||||
<button id="btn_download_list" class="toolbar_button button_full_width" style="display: none;">
|
||||
<i class="icon">save</i>
|
||||
<span>DL all files</span>
|
||||
</button>
|
||||
<button id="btn_copy" class="toolbar_button button_full_width">
|
||||
<i class="icon">content_copy</i>
|
||||
<span><u>C</u>opy link</span>
|
||||
</button>
|
||||
<button id="btn_share" class="toolbar_button button_full_width">
|
||||
<i class="icon">share</i>
|
||||
<span>Share</span>
|
||||
</button>
|
||||
<button id="btn_qr_code" class="toolbar_button button_full_width">
|
||||
<i class="icon">qr_code</i>
|
||||
<span>QR code</span>
|
||||
</button>
|
||||
<button id="btn_shuffle" class="toolbar_button button_full_width" style="display: none;" title="Randomize the order of the files in this list">
|
||||
<i class="icon">shuffle</i>
|
||||
<span>Shuffle ☐</span>
|
||||
</button>
|
||||
<button id="btn_details" class="toolbar_button button_full_width">
|
||||
<i class="icon">help</i>
|
||||
<span>Deta<u>i</u>ls</span>
|
||||
</button>
|
||||
<hr/>
|
||||
<button id="btn_edit" class="toolbar_button button_full_width" style="display: none;">
|
||||
<i class="icon">edit</i>
|
||||
<span><u>E</u>dit</span>
|
||||
</button>
|
||||
<button id="btn_grab" class="toolbar_button button_full_width" style="display: none;" title="Copy this file to your own pixeldrain account">
|
||||
<i class="icon">save_alt</i>
|
||||
<span><u>G</u>rab file</span>
|
||||
</button>
|
||||
<button id="btn_embed" class="toolbar_button button_full_width" title="Include this file in your own webpages">
|
||||
<i class="icon">code</i>
|
||||
<span>E<u>m</u>bed</span>
|
||||
</button>
|
||||
<button id="btn_report_abuse" class="toolbar_button button_full_width" title="Report abuse in this file">
|
||||
<i class="icon">flag</i>
|
||||
<span>Report</span>
|
||||
</button>
|
||||
<br/>
|
||||
|
||||
{{ if and .Other.FileAdsEnabled .Other.UserAdsEnabled }}
|
||||
<hr/>
|
||||
Tired of ads?<br/>
|
||||
Files expiring too soon?<br/>
|
||||
<a class="button button_highlight" href="/click/7wy9gg2J?target=%2F%23pro">
|
||||
<svg style="float: left; width: 2em; height: 2em; fill: currentColor; margin-right: 4px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M64.1102,0.1004 C44.259,0.1004 28.1086,16.2486 28.1086,36.0986 C28.1086,55.8884 44.259,71.989 64.1102,71.989 C83.9,71.989 100,55.8884 100,36.0986 C100,16.2486 83.9,0.1004 64.1102,0.1004"/>
|
||||
<polygon points=".012 95.988 17.59 95.988 17.59 .1 .012 .1"/>
|
||||
</g>
|
||||
</svg>
|
||||
Become a Patron!
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
<!-- This frame will load the download URL when a download button is pressed -->
|
||||
<iframe id="download_frame" style="display: none; width: 1px; height: 1px;"></iframe>
|
||||
</div></div></div>
|
||||
|
||||
<div id="sharebar" class="file_viewer_sharebar">
|
||||
Share on:<br/>
|
||||
<button class="sharebar-button button_full_width" onclick="window.open('mailto:please@set.address?subject=File%20on%20pixeldrain&body=' + window.location.href);">
|
||||
{{template `email.svg` .}}<br/>E-Mail
|
||||
</button>
|
||||
<button class="sharebar-button button_full_width" onclick="window.open('https://www.reddit.com/submit?url=' + window.location.href);">
|
||||
{{template `reddit.svg` .}}<br/>Reddit
|
||||
</button>
|
||||
<button class="sharebar-button button_full_width" onclick="window.open('https://twitter.com/share?url=' + window.location.href);">
|
||||
{{template `twitter.svg` .}}<br/>Twitter
|
||||
</button>
|
||||
<button class="sharebar-button button_full_width" onclick="window.open('http://www.facebook.com/sharer.php?u=' + window.location.href);">
|
||||
{{template `facebook.svg` .}}<br/>Facebook
|
||||
</button>
|
||||
<button class="sharebar-button button_full_width" onclick="window.open('http://www.tumblr.com/share/link?url=' + window.location.href);">
|
||||
{{template `tumblr.svg` .}}<br/>Tumblr
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="filepreview" class="file_viewer_file_preview checkers">
|
||||
<div class="center" style="width: 100px; height: 100px;">{{template "spinner.svg" .}}</div>
|
||||
</div>
|
||||
|
||||
<div id="skyscraper" class="skyscraper">
|
||||
<button id="btn_skyscraper_close" class="round">
|
||||
<i class="icon">close</i> Close ad
|
||||
</button>
|
||||
<div id="skyscraper_ad_space" class="skyscraper_ad_space"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sponsors" class="sponsors">
|
||||
{{ if and .Other.FileAdsEnabled .Other.UserAdsEnabled }}
|
||||
{{ template "banner_ads" . }}
|
||||
{{ else if not .Other.UserAdsEnabled }}
|
||||
<div style="text-align: center; line-height: 1.3em; font-size: 13px;">
|
||||
Thank you for supporting pixeldrain!
|
||||
</div>
|
||||
{{ else if not .Other.FileAdsEnabled }}
|
||||
<div style="text-align: center; line-height: 1.3em; font-size: 13px;">
|
||||
The uploader of this file disabled advertisements. You can do the same for <a href="/#pro">only €2 per month</a>!
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="tpl_details_popup">
|
||||
<table class="info_file_details" style="min-width: 100%;"></table>
|
||||
|
||||
<div class="info_about">
|
||||
<h3>Downloads</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 150px;">
|
||||
<canvas id="downloads_chart"></canvas>
|
||||
</div>
|
||||
<h3>Views</h3>
|
||||
<div class="chart-container" style="position: relative; width: 100%; height: 150px;">
|
||||
<canvas id="views_chart"></canvas>
|
||||
</div>
|
||||
<p style="text-align: center">
|
||||
Charts rendered by the amazing <a href="https://www.chartjs.org/" target="_blank">Chart.js</a>.
|
||||
</p>
|
||||
|
||||
<h3>About</h3>
|
||||
Pixeldrain is a file sharing platform.
|
||||
<a href="/" target="_blank">Visit the home page for more information.</a>
|
||||
|
||||
<h3>Keyboard Controls</h3>
|
||||
<table style="max-width: 100%;">
|
||||
<tr><td colspan="2">File Shortcuts</td></tr>
|
||||
<tr><td>c</td><td> = Copy URL of this page</td></tr>
|
||||
<tr><td>i</td><td> = Toggle details window (this window) (<b><u>i</u></b>nfo)</td></tr>
|
||||
<tr><td>s</td><td> = Download the file you are currently viewing (<b><u>s</u></b>ave)</td></tr>
|
||||
<tr><td>q</td><td> = Close the window (<b><u>q</u></b>uit)</td></tr>
|
||||
<tr><td colspan="2">List Shortcuts</td></tr>
|
||||
<tr><td>a or ←</td><td> = View previous item in list</td></tr>
|
||||
<tr><td>d or →</td><td> = View next item in list</td></tr>
|
||||
<tr><td>r</td><td> = Toggle shuffle (<b><u>r</u></b>andom)</td></tr>
|
||||
<tr><td>SHIFT + s</td><td> = Download all the files in the list as a zip archive</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="tpl_edit_file">
|
||||
<div class="edit_file_notification" style="display: none;"></div>
|
||||
<h3>Rename</h3>
|
||||
<form class="edit_file_name_form" style="display: flex; width: 100%">
|
||||
<input class="edit_file_name_field" type="text" style="flex: 1 1 auto"/>
|
||||
<button class="edit_file_name_submit" role="submit" style="flex: 0 0 auto">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</form>
|
||||
<h3>Delete</h3>
|
||||
<p>
|
||||
When you delete a file it cannot be recovered.
|
||||
Nobody will be able to download it and the link will
|
||||
stop working. The file will also disappear from any
|
||||
lists it's contained in.
|
||||
</p>
|
||||
<div style="text-align: center;">
|
||||
<button class="button_red btn_delete_file">
|
||||
<i class="icon small">delete</i> Delete this file
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="tpl_captcha_popup">
|
||||
<div class="captcha_text"></div>
|
||||
<br/>
|
||||
<div class="captcha_popup_captcha" style="text-align: center;"></div>
|
||||
</template>
|
||||
|
||||
<template id="tpl_embed_popup">
|
||||
<p>
|
||||
You can embed pixeldrain's file viewer in your own web pages. We
|
||||
have created a special HTML code which renders a minimalistic
|
||||
version of the file viewer where the title bar is a bit thinner and
|
||||
the toolbar is collapsed by default.
|
||||
</p>
|
||||
<p>
|
||||
Unless it was uploaded using a pixeldrain Pro account the embedded
|
||||
file will also show advertisements.
|
||||
</p>
|
||||
<h3>Code</h3>
|
||||
<textarea class="embed_html_code" style="width: 100%; height: 4em; margin: 0;"></textarea>
|
||||
<br/>
|
||||
<button class="embed_copy_html"><i class="icon">content_copy</i> Copy HTML</button>
|
||||
<button class="embed_show_preview"><i class="icon">visibility</i> Show example</button>
|
||||
<h3>Example</h3>
|
||||
<div class="embed_preview_area" style="text-align: center;"></div>
|
||||
</template>
|
||||
|
||||
<template id="tpl_report_abuse_popup">
|
||||
<p>
|
||||
If you think this file violates pixeldrain's
|
||||
<a href="/about#content-policy">content policy</a> you can
|
||||
report it for moderation with this form. You cannot report
|
||||
copyright abuse with this form, send a formal DMCA notification
|
||||
to the
|
||||
<a href="/about#content-policy">abuse e-mail address</a>
|
||||
instead.
|
||||
</p>
|
||||
<form class="abuse_type_form" style="width: 100%">
|
||||
<h3>Abuse type</h3>
|
||||
<p>
|
||||
Which type of abuse is shown in this file? Pick the most
|
||||
appropriate one.
|
||||
</p>
|
||||
<label for="abuse_type_terrorism">
|
||||
<input type="radio" id="abuse_type_terrorism" name="abuse_type" value="terrorism">
|
||||
<b>Terrorism</b>: Videos, images or audio fragments showing
|
||||
or promoting the use of intentional violence to achieve
|
||||
political aims.
|
||||
</label>
|
||||
<label for="abuse_type_gore">
|
||||
<input type="radio" id="abuse_type_gore" name="abuse_type" value="gore">
|
||||
<b>Gore</b>: Graphic and shocking videos or images depicting
|
||||
severe harm to humans (or animals).
|
||||
</label>
|
||||
<label for="abuse_type_child_abuse">
|
||||
<input type="radio" id="abuse_type_child_abuse" name="abuse_type" value="child_abuse">
|
||||
<b>Child abuse</b>: Videos or images depicting inappropriate
|
||||
touching or nudity of minors.
|
||||
</label>
|
||||
<label for="abuse_type_malware">
|
||||
<input type="radio" id="abuse_type_malware" name="abuse_type" value="malware">
|
||||
<b>Malware</b>: Software programs designed to cause harm to
|
||||
computer systems.
|
||||
</label>
|
||||
|
||||
<h3>Send</h3>
|
||||
<div class="abuse_report_notification" style="display: none;"></div>
|
||||
<p>
|
||||
Abuse reports are manually reviewed. Normally this shouldn't
|
||||
take more than 24 hours. During busy periods it can take
|
||||
longer.
|
||||
</p>
|
||||
<div style="text-align: right;">
|
||||
<button class="button_highlight abuse_report_submit" role="submit">
|
||||
<i class="icon">send</i> Send
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<template id="intro_popup">
|
||||
<h3>Upload your own files here!</h3>
|
||||
<p>
|
||||
On pixeldrain you can share your files with large or small
|
||||
groups of people. The sky is the limit!
|
||||
</p>
|
||||
<button class="intro_popup_close button_highlight round" style="float: right; margin: 0 10px 10px 0;">
|
||||
<i class="icon">check</i> Got it!
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script src="/res/script/Chart.min.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
let apiEndpoint = '{{.APIEndpoint}}';
|
||||
let captchaKey = '{{.Other.CaptchaKey}}';
|
||||
let embeddedViewer = {{.Other.Embedded}};
|
||||
let userAuthenticated = {{.Authenticated}};
|
||||
let skyscraperType = "{{.Other.AdSkyscraperType}}"
|
||||
|
||||
{{template `util.js`}}
|
||||
{{template `drawGraph.js`}}
|
||||
{{template `Modal.js`}}
|
||||
{{template `Toolbar.js`}}
|
||||
{{template `Skyscraper.js`}}
|
||||
{{template `EditWindow.js`}}
|
||||
{{template `EmbedWindow.js`}}
|
||||
{{template `QRCodeWindow.js`}}
|
||||
{{template `DetailsWindow.js`}}
|
||||
{{template `AbuseReportWindow.js`}}
|
||||
{{template `ListNavigator.js`}}
|
||||
{{template `IntroPopup.js`}}
|
||||
{{template `Viewer.js`}}
|
||||
|
||||
{{template `AbuseViewer.js`}}
|
||||
{{template `ImageViewer.js`}}
|
||||
{{template `VideoViewer.js`}}
|
||||
{{template `AudioViewer.js`}}
|
||||
{{template `PDFViewer.js`}}
|
||||
{{template `TextViewer.js`}}
|
||||
{{template `FileViewer.js`}}
|
||||
|
||||
// DOMContentLoaded fires when the DOM tree has been parsed, but
|
||||
// before the assets have loaded
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
// This info gets filled in on the server side to prevent having to
|
||||
// make an API call right after the page loads. Just to slice
|
||||
// another few milliseconds from the load time :)
|
||||
new Viewer('{{.Other.Type}}', '{{.Other.ViewToken}}', {{.Other.APIResponse}})
|
||||
})
|
||||
</script>
|
||||
|
||||
{{ if and .Other.FileAdsEnabled .Other.UserAdsEnabled }}
|
||||
{{ template "analytics" }}
|
||||
{{ template "floating_ads" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
@@ -2,7 +2,6 @@ package webcontroller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -24,113 +23,19 @@ func browserCompat(ua string) bool {
|
||||
return strings.Contains(ua, "MSIE") || strings.Contains(ua, "Trident/7.0")
|
||||
}
|
||||
|
||||
type viewerData struct {
|
||||
Type string // file or list
|
||||
CaptchaKey string
|
||||
ViewToken string
|
||||
AdBannerType int
|
||||
AdSkyscraperType string
|
||||
AdFloaterType int
|
||||
AdPopupType int
|
||||
FileAdsEnabled bool
|
||||
UserAdsEnabled bool
|
||||
Embedded bool
|
||||
APIResponse interface{}
|
||||
}
|
||||
|
||||
func (vd *viewerData) adType(files []pixelapi.ListFile) {
|
||||
if len(files) == 0 {
|
||||
return
|
||||
} else if !vd.FileAdsEnabled || !vd.UserAdsEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
var avgSize int64
|
||||
for _, v := range files {
|
||||
avgSize += v.Size
|
||||
}
|
||||
avgSize /= int64(len(files))
|
||||
|
||||
const (
|
||||
// Banners
|
||||
none = 0
|
||||
aAds = 1
|
||||
patreon = 2
|
||||
adshares = 3
|
||||
amarulaSolutions = 4
|
||||
adMaven = 5
|
||||
adSterra = 6
|
||||
brave = 7
|
||||
pdpro1 = 8
|
||||
pdpro2 = 9
|
||||
pdpro3 = 10
|
||||
pdpro4 = 11
|
||||
clickAduBanner = 12
|
||||
amarulaElectronics = 13
|
||||
adsPlus = 14
|
||||
pixFuture = 15
|
||||
publisherrest1 = 16
|
||||
publisherrest2 = 17
|
||||
publisherrest3 = 18
|
||||
|
||||
// Skyscrapers
|
||||
aAdsSkyscraper = "a-ads"
|
||||
pixfutureSkyscraper = "pixfuture"
|
||||
adsPlusSkyscraper = "adsplus"
|
||||
adsharesSkyscraper = "adshares"
|
||||
|
||||
// Floaters
|
||||
// propellerFloat = 1
|
||||
// adSterraFloat = 2
|
||||
// adMavenFloat = 3
|
||||
|
||||
// Popunders
|
||||
// clickAduPopup = 1
|
||||
// propellerPopup = 2
|
||||
)
|
||||
|
||||
// Intn returns a number up to n, but never n itself. So to get a random 0
|
||||
// or 1 we need to give it n=2. We can use this function to make other
|
||||
// splits like 1/3 1/4, etc
|
||||
|
||||
switch i := rand.Intn(20); i {
|
||||
case 0:
|
||||
vd.AdBannerType = publisherrest1 // 5%, total 5%
|
||||
case 1:
|
||||
vd.AdBannerType = publisherrest2 // 5%, total 10%
|
||||
case 2:
|
||||
vd.AdBannerType = publisherrest3 // 5%, total 15%
|
||||
case 3, 4, 5:
|
||||
vd.AdBannerType = brave // 15%, total 30%
|
||||
case 6, 7, 8, 9, 10, 11, 12:
|
||||
vd.AdBannerType = adsPlus // 35%, total 65%
|
||||
case 13, 14, 15, 16, 17, 18, 19:
|
||||
vd.AdBannerType = pixFuture // 35%, total 100%
|
||||
default:
|
||||
panic(fmt.Errorf("random number generator returned unrecognised number: %d", i))
|
||||
}
|
||||
|
||||
switch i := rand.Intn(2); i {
|
||||
case 0:
|
||||
vd.AdSkyscraperType = aAdsSkyscraper
|
||||
case 1:
|
||||
vd.AdSkyscraperType = pixfutureSkyscraper
|
||||
default:
|
||||
panic(fmt.Errorf("random number generator returned unrecognised number: %d", i))
|
||||
}
|
||||
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"`
|
||||
}
|
||||
|
||||
// ServeFileViewer controller for GET /u/:id
|
||||
func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
var err error
|
||||
if p.ByName("id") == "demo" {
|
||||
wc.serveFileViewerDemo(w, r, 1, "a-ads") // Required for a-ads.com quality check
|
||||
return
|
||||
} else if p.ByName("id") == "adsplus" {
|
||||
wc.serveFileViewerDemo(w, r, 14, "")
|
||||
return
|
||||
} else if p.ByName("id") == "pixfuture" {
|
||||
wc.serveFileViewerDemo(w, r, 15, "")
|
||||
wc.serveViewerDemo(w, r) // Required for a-ads.com quality check
|
||||
return
|
||||
}
|
||||
|
||||
@@ -141,9 +46,9 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
var ids = strings.Split(p.ByName("id"), ",")
|
||||
|
||||
templateData := wc.newTemplateData(w, r)
|
||||
var templateData = wc.newTemplateData(w, r)
|
||||
|
||||
var files []pixelapi.ListFile
|
||||
for _, id := range ids {
|
||||
@@ -166,13 +71,11 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
|
||||
|
||||
templateData.OGData = wc.metadataFromFile(files[0].FileInfo)
|
||||
|
||||
var vd = viewerData{
|
||||
var vd = fileViewerData{
|
||||
CaptchaKey: wc.captchaKey(),
|
||||
ViewToken: wc.viewTokenOrBust(),
|
||||
FileAdsEnabled: files[0].ShowAds,
|
||||
UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay),
|
||||
}
|
||||
vd.adType(files)
|
||||
|
||||
if len(ids) > 1 {
|
||||
templateData.Title = fmt.Sprintf("%d files on pixeldrain", len(files))
|
||||
@@ -195,11 +98,6 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
|
||||
|
||||
templateData.Other = vd
|
||||
|
||||
var templateName = "file_viewer"
|
||||
if browserCompat(r.UserAgent()) {
|
||||
templateName = "file_viewer_compat"
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if file.AbuseType != "" {
|
||||
w.WriteHeader(http.StatusUnavailableForLegalReasons)
|
||||
@@ -207,47 +105,25 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
}
|
||||
|
||||
var templateName = "file_viewer_svelte"
|
||||
if browserCompat(r.UserAgent()) {
|
||||
templateName = "file_viewer_compat"
|
||||
}
|
||||
|
||||
err = wc.templates.Get().ExecuteTemplate(w, templateName, templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error executing template file_viewer: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (wc *WebController) serveFileViewerDemo(w http.ResponseWriter, r *http.Request, banner int, scraper string) {
|
||||
templateData := wc.newTemplateData(w, r)
|
||||
templateData.Other = viewerData{
|
||||
Type: "file",
|
||||
CaptchaKey: wc.captchaSiteKey,
|
||||
AdBannerType: banner, // Always show a-ads on the demo page
|
||||
AdSkyscraperType: scraper,
|
||||
FileAdsEnabled: true,
|
||||
UserAdsEnabled: true,
|
||||
APIResponse: map[string]interface{}{
|
||||
"id": "demo",
|
||||
"name": "Demo file",
|
||||
"date_upload": "2017-01-01 12:34:56",
|
||||
"date_lastview": "2017-01-01 12:34:56",
|
||||
"size": 123456789,
|
||||
"views": 1,
|
||||
"bandwidth_used": 123456789,
|
||||
"mime_type": "text/demo",
|
||||
"description": "A file to demonstrate the viewer page",
|
||||
"mime_image": "/res/img/mime/text.png",
|
||||
"thumbnail": "/res/img/mime/text.png",
|
||||
"abuse_type": "",
|
||||
},
|
||||
}
|
||||
err := wc.templates.Get().ExecuteTemplate(w, "file_viewer", templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error rendering demo file: %s", err)
|
||||
}
|
||||
func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
// If the user agent is Wget we redirect it to the API so that the file can
|
||||
// be downloaded directly
|
||||
if strings.HasPrefix(r.UserAgent(), "Wget/") {
|
||||
http.Redirect(w, r, "/api/list/"+p.ByName("id")+"/zip", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// ServeListViewer controller for GET /l/:id
|
||||
func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
var templateData = wc.newTemplateData(w, r)
|
||||
var list, err = templateData.PixelAPI.GetListID(p.ByName("id"))
|
||||
if err != nil {
|
||||
@@ -269,26 +145,19 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
|
||||
|
||||
templateData.Title = fmt.Sprintf("%s ~ pixeldrain", list.Title)
|
||||
templateData.OGData = wc.metadataFromList(list)
|
||||
var vd = viewerData{
|
||||
var vd = fileViewerData{
|
||||
Type: "list",
|
||||
CaptchaKey: wc.captchaSiteKey,
|
||||
ViewToken: wc.viewTokenOrBust(),
|
||||
FileAdsEnabled: list.Files[0].ShowAds,
|
||||
UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay),
|
||||
APIResponse: list,
|
||||
}
|
||||
vd.adType(list.Files)
|
||||
|
||||
if _, ok := r.URL.Query()["embed"]; ok {
|
||||
vd.Embedded = true
|
||||
}
|
||||
templateData.Other = vd
|
||||
|
||||
var templateName = "file_viewer"
|
||||
if browserCompat(r.UserAgent()) {
|
||||
templateName = "file_viewer_compat"
|
||||
}
|
||||
|
||||
for _, file := range list.Files {
|
||||
if file.AbuseType != "" {
|
||||
w.WriteHeader(http.StatusUnavailableForLegalReasons)
|
||||
@@ -296,8 +165,44 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
}
|
||||
|
||||
var templateName = "file_viewer_svelte"
|
||||
if browserCompat(r.UserAgent()) {
|
||||
templateName = "file_viewer_compat"
|
||||
}
|
||||
|
||||
err = wc.templates.Get().ExecuteTemplate(w, templateName, templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error executing template file_viewer: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (wc *WebController) serveViewerDemo(w http.ResponseWriter, r *http.Request) {
|
||||
templateData := wc.newTemplateData(w, r)
|
||||
templateData.Other = fileViewerData{
|
||||
Type: "file",
|
||||
CaptchaKey: wc.captchaSiteKey,
|
||||
UserAdsEnabled: true,
|
||||
APIResponse: map[string]interface{}{
|
||||
"id": "demo",
|
||||
"name": "Demo file",
|
||||
"date_upload": "2017-01-01 12:34:56",
|
||||
"date_lastview": "2017-01-01 12:34:56",
|
||||
"size": 123456789,
|
||||
"views": 1,
|
||||
"bandwidth_used": 123456789,
|
||||
"mime_type": "text/demo",
|
||||
"description": "A file to demonstrate the viewer page",
|
||||
"mime_image": "/res/img/mime/text.png",
|
||||
"thumbnail": "/res/img/mime/text.png",
|
||||
"abuse_type": "",
|
||||
"show_ads": true,
|
||||
},
|
||||
}
|
||||
err := wc.templates.Get().ExecuteTemplate(w, "file_viewer_svelte", templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error rendering demo file: %s", err)
|
||||
}
|
||||
}
|
||||
|
@@ -1,196 +0,0 @@
|
||||
package webcontroller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fornaxian.tech/pixeldrain_api_client/pixelapi"
|
||||
"github.com/Fornaxian/log"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
// ServeFileViewer controller for GET /u/:id
|
||||
func (wc *WebController) serveSvelteFile(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
if p.ByName("id") == "demo" {
|
||||
wc.serveSvelteViewerDemo(w, r) // Required for a-ads.com quality check
|
||||
return
|
||||
}
|
||||
|
||||
// If the user agent is Wget we redirect it to the API so that the file can
|
||||
// be downloaded directly
|
||||
if strings.HasPrefix(r.UserAgent(), "Wget/") {
|
||||
http.Redirect(w, r, "/api/file/"+p.ByName("id"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
var ids = strings.Split(p.ByName("id"), ",")
|
||||
var templateData = wc.newTemplateData(w, r)
|
||||
|
||||
var files []pixelapi.ListFile
|
||||
for _, id := range ids {
|
||||
inf, err := templateData.PixelAPI.GetFileInfo(id)
|
||||
if err != nil {
|
||||
if pixelapi.ErrIsServerError(err) {
|
||||
wc.templates.Get().ExecuteTemplate(w, "500", templateData)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
files = append(files, pixelapi.ListFile{FileInfo: inf})
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
wc.templates.Get().ExecuteTemplate(w, "file_not_found", templateData)
|
||||
return
|
||||
}
|
||||
|
||||
templateData.OGData = wc.metadataFromFile(files[0].FileInfo)
|
||||
|
||||
var vd = fileViewerData{
|
||||
CaptchaKey: wc.captchaKey(),
|
||||
ViewToken: wc.viewTokenOrBust(),
|
||||
UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay),
|
||||
}
|
||||
|
||||
if len(ids) > 1 {
|
||||
templateData.Title = fmt.Sprintf("%d files on pixeldrain", len(files))
|
||||
vd.Type = "list"
|
||||
vd.APIResponse = pixelapi.ListInfo{
|
||||
Success: true,
|
||||
Title: "Multiple files",
|
||||
DateCreated: time.Now(),
|
||||
Files: files,
|
||||
}
|
||||
} else {
|
||||
templateData.Title = fmt.Sprintf("%s ~ pixeldrain", files[0].Name)
|
||||
vd.Type = "file"
|
||||
vd.APIResponse = files[0].FileInfo
|
||||
}
|
||||
|
||||
if _, ok := r.URL.Query()["embed"]; ok {
|
||||
vd.Embedded = true
|
||||
}
|
||||
|
||||
templateData.Other = vd
|
||||
|
||||
for _, file := range files {
|
||||
if file.AbuseType != "" {
|
||||
w.WriteHeader(http.StatusUnavailableForLegalReasons)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var templateName = "file_viewer_svelte"
|
||||
if browserCompat(r.UserAgent()) {
|
||||
templateName = "file_viewer_compat"
|
||||
}
|
||||
|
||||
err = wc.templates.Get().ExecuteTemplate(w, templateName, templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error executing template file_viewer: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WebController) serveSvelteList(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
// If the user agent is Wget we redirect it to the API so that the file can
|
||||
// be downloaded directly
|
||||
if strings.HasPrefix(r.UserAgent(), "Wget/") {
|
||||
http.Redirect(w, r, "/api/list/"+p.ByName("id")+"/zip", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
var templateData = wc.newTemplateData(w, r)
|
||||
var list, err = templateData.PixelAPI.GetListID(p.ByName("id"))
|
||||
if err != nil {
|
||||
if err, ok := err.(pixelapi.Error); ok && err.Status == http.StatusNotFound {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
wc.templates.Get().ExecuteTemplate(w, "list_not_found", templateData)
|
||||
} else {
|
||||
log.Error("API request error occurred: %s", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
wc.templates.Get().ExecuteTemplate(w, "500", templateData)
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(list.Files) == 0 {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
wc.templates.Get().ExecuteTemplate(w, "list_not_found", templateData)
|
||||
return
|
||||
}
|
||||
|
||||
templateData.Title = fmt.Sprintf("%s ~ pixeldrain", list.Title)
|
||||
templateData.OGData = wc.metadataFromList(list)
|
||||
var vd = fileViewerData{
|
||||
Type: "list",
|
||||
CaptchaKey: wc.captchaSiteKey,
|
||||
ViewToken: wc.viewTokenOrBust(),
|
||||
UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay),
|
||||
APIResponse: list,
|
||||
}
|
||||
|
||||
if _, ok := r.URL.Query()["embed"]; ok {
|
||||
vd.Embedded = true
|
||||
}
|
||||
templateData.Other = vd
|
||||
|
||||
for _, file := range list.Files {
|
||||
if file.AbuseType != "" {
|
||||
w.WriteHeader(http.StatusUnavailableForLegalReasons)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var templateName = "file_viewer_svelte"
|
||||
if browserCompat(r.UserAgent()) {
|
||||
templateName = "file_viewer_compat"
|
||||
}
|
||||
|
||||
err = wc.templates.Get().ExecuteTemplate(w, templateName, templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error executing template file_viewer: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (wc *WebController) serveSvelteViewerDemo(w http.ResponseWriter, r *http.Request) {
|
||||
templateData := wc.newTemplateData(w, r)
|
||||
templateData.Other = fileViewerData{
|
||||
Type: "file",
|
||||
CaptchaKey: wc.captchaSiteKey,
|
||||
UserAdsEnabled: true,
|
||||
APIResponse: map[string]interface{}{
|
||||
"id": "demo",
|
||||
"name": "Demo file",
|
||||
"date_upload": "2017-01-01 12:34:56",
|
||||
"date_lastview": "2017-01-01 12:34:56",
|
||||
"size": 123456789,
|
||||
"views": 1,
|
||||
"bandwidth_used": 123456789,
|
||||
"mime_type": "text/demo",
|
||||
"description": "A file to demonstrate the viewer page",
|
||||
"mime_image": "/res/img/mime/text.png",
|
||||
"thumbnail": "/res/img/mime/text.png",
|
||||
"abuse_type": "",
|
||||
"show_ads": true,
|
||||
},
|
||||
}
|
||||
err := wc.templates.Get().ExecuteTemplate(w, "file_viewer_svelte", templateData)
|
||||
if err != nil && !strings.Contains(err.Error(), "broken pipe") {
|
||||
log.Error("Error rendering demo file: %s", err)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user