Online file previews
diff --git a/svelte/rollup.config.js b/svelte/rollup.config.js
index 3a31903..95832cc 100644
--- a/svelte/rollup.config.js
+++ b/svelte/rollup.config.js
@@ -32,6 +32,7 @@ export default [
"file_viewer",
"filesystem",
"modal",
+ "user_home",
"user_buckets",
"user_file_manager",
"admin_panel",
diff --git a/svelte/src/admin_panel/AdminPanel.svelte b/svelte/src/admin_panel/AdminPanel.svelte
index a344d02..a024bcd 100644
--- a/svelte/src/admin_panel/AdminPanel.svelte
+++ b/svelte/src/admin_panel/AdminPanel.svelte
@@ -25,42 +25,44 @@ onMount(() => {
-
{navigate("status", "Status")}}>
- home
- Status
-
-
- block
- Block files
-
-
{navigate("abuse_reports", "Abuse reports")}}>
- flag
- User abuse reports
-
-
{navigate("abuse_reporters", "Abuse reporters")}}>
- report
- E-mail abuse reporters
-
-
{navigate("ip_bans", "IP bans")}}>
- remove_circle
- IP bans
-
-
- edit
- Update global settings
-
+
{#if page === "status"}
diff --git a/svelte/src/user_home.js b/svelte/src/user_home.js
new file mode 100644
index 0000000..7956dc9
--- /dev/null
+++ b/svelte/src/user_home.js
@@ -0,0 +1,8 @@
+import App from './user_home/Router.svelte';
+
+const app = new App({
+ target: document.getElementById("page_content"),
+ props: {}
+});
+
+export default app;
diff --git a/svelte/src/user_home/AccountSettings.svelte b/svelte/src/user_home/AccountSettings.svelte
new file mode 100644
index 0000000..ee62a83
--- /dev/null
+++ b/svelte/src/user_home/AccountSettings.svelte
@@ -0,0 +1,126 @@
+
+
+
+
+
Change password
+
+
+
+
+
Change e-mail address
+
+
+
+
+
Change name
+
+
+
+
+
+
+
diff --git a/svelte/src/user_home/Home.svelte b/svelte/src/user_home/Home.svelte
new file mode 100644
index 0000000..ed92575
--- /dev/null
+++ b/svelte/src/user_home/Home.svelte
@@ -0,0 +1,286 @@
+
+
+
+
+
Account information
+
+ Username: {window.user.username}
+ E-mail address: {window.user.email}
+
+ Supporter level: {window.user.subscription.name}
+ {#if window.user.subscription.type === "patreon"}
+ (Manage subscription )
+ {/if}
+
+
+ Advertisements when viewing files:
+ {#if window.user.subscription.disable_ad_display}No{:else}Yes{/if}
+
+
+ Advertisements on your uploaded files:
+ {#if window.user.subscription.disable_ads_on_files}No{:else}Yes{/if}
+
+ {#if window.user.subscription.file_expiry_days > 0}
+ Files expire after {window.user.subscription.file_expiry_days} days
+ {:else}
+ Files never expire
+ {/if}
+
+
+
+
+ Storage:
+ {formatDataVolume(storage_space_used, 3)}
+ out of
+ {formatDataVolume(window.user.subscription.storage_space, 3)}
+
+
+
+ Direct link bandwidth:
+ {formatDataVolume(direct_link_bandwidth_used, 3)}
+ out of
+ {formatDataVolume(window.user.subscription.direct_linking_bandwidth, 3)}
+ (
More information about direct linking )
+
+
+
+
Exports
+
+
+
Statistics
+
+ Here you can see how often your files are viewed, downloaded
+ and how much bandwidth they consume. The buttons at the top
+ can be pressed to adjust the timeframe. If you choose 'Day'
+ the statistics will be updated periodically. No need to
+ refresh the page.
+
+
+
+ { update_graphs(1440, 1, true) }}
+ class:button_highlight={graph_timespan == 1440}>
+ Day (1m)
+
+ { update_graphs(10080, 10, false) }}
+ class:button_highlight={graph_timespan == 10080}>
+ Week (10m)
+
+ { update_graphs(20160, 60, false) }}
+ class:button_highlight={graph_timespan == 20160}>
+ Two Weeks (1h)
+
+ { update_graphs(43200, 1440, false) }}
+ class:button_highlight={graph_timespan == 43200}>
+ Month (1d)
+
+ { update_graphs(131400, 1440, false) }}
+ class:button_highlight={graph_timespan == 131400}>
+ Quarter (1d)
+
+ { update_graphs(525600, 1440, false) }}
+ class:button_highlight={graph_timespan == 525600}>
+ Year (1d)
+
+ { update_graphs(1051200, 1440, false) }}
+ class:button_highlight={graph_timespan == 1051200}>
+ Two Years (1d)
+
+
+ Total usage from {time_start} to {time_end}
+ {formatThousands(total_views)} views,
+ {formatThousands(total_downloads)} downloads,
+ {formatDataVolume(total_bandwidth, 3)} bandwidth and
+ {formatDataVolume(total_direct_link, 3)} direct link bandwidth
+
+
+
Views
+
+ A view is counted when someone visits the download page of one
+ of your files. Views are unique per user per file.
+
+
+
+
+
Downloads
+
+ Downloads are counted when a user clicks the download button
+ on one of your files. It does not matter whether the
+ download is completed or not, only the start of the download
+ is counted.
+
+
+
+
+
Bandwidth
+
+ This is how much bandwidth your files are using in total.
+ Bandwidth is used when a file is tranferred from a
+ pixeldrain server to a user who is downloading the file.
+ When a 5 MB file is downloaded 8 times it has used 40 MB of
+ bandwidth.
+
+
+
+
+
Direct link bandwidth
+
+ When a file is downloaded without going through pixeldrain's
+ download page it counts as a direct download. Because direct
+ downloads cost us bandwidth and don't generate any ad
+ revenue we have to limit them. When your direct link
+ bandwidth runs out people will be asked to do a test before
+ they can download your files. See our
+ subscription options to get more direct
+ linking bandwidth.
+
+
+
+
+
+
diff --git a/svelte/src/user_home/Router.svelte b/svelte/src/user_home/Router.svelte
new file mode 100644
index 0000000..61539e7
--- /dev/null
+++ b/svelte/src/user_home/Router.svelte
@@ -0,0 +1,50 @@
+
+
+
+
+
diff --git a/svelte/src/util/Chart.svelte b/svelte/src/util/Chart.svelte
index b35e789..dcc8b6b 100644
--- a/svelte/src/util/Chart.svelte
+++ b/svelte/src/util/Chart.svelte
@@ -15,7 +15,7 @@ export const update = () => {
return chart_object.update()
}
-Chart.defaults.global.defaultFontColor = "#b3b3b3";
+Chart.defaults.global.defaultFontColor = "#cccccc";
Chart.defaults.global.defaultFontSize = 15;
Chart.defaults.global.defaultFontFamily = "system-ui, sans-serif";
Chart.defaults.global.maintainAspectRatio = false;
diff --git a/svelte/src/util/Form.svelte b/svelte/src/util/Form.svelte
new file mode 100644
index 0000000..0f34d16
--- /dev/null
+++ b/svelte/src/util/Form.svelte
@@ -0,0 +1,229 @@
+
+
+
+
+
diff --git a/webcontroller/ad_click.go b/webcontroller/ad_click.go
index 5eecc59..9bfc068 100644
--- a/webcontroller/ad_click.go
+++ b/webcontroller/ad_click.go
@@ -16,7 +16,7 @@ func (wc *WebController) serveAdClick(w http.ResponseWriter, r *http.Request, p
// The Real IP is used in the API server to determine that the view is not
// fake
- var api = wc.api.RealIP(util.RemoteAddress(r))
+ var api = wc.api.RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent())
// Log a view on the file
if err := api.PostFileView(p.ByName("id"), wc.viewTokenOrBust()); err != nil {
diff --git a/webcontroller/file_preview.go b/webcontroller/file_preview.go
index 888f863..571c3a2 100644
--- a/webcontroller/file_preview.go
+++ b/webcontroller/file_preview.go
@@ -21,7 +21,7 @@ func (wc *WebController) serveFilePreview(w http.ResponseWriter, r *http.Request
}
apiKey, _ := wc.getAPIKey(r)
- api := wc.api.Login(apiKey).RealIP(util.RemoteAddress(r))
+ api := wc.api.Login(apiKey).RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent())
file, err := api.GetFileInfo(p.ByName("id")) // TODO: Error handling
if err != nil {
diff --git a/webcontroller/file_viewer.go b/webcontroller/file_viewer.go
index 24a3a6b..d6e3376 100644
--- a/webcontroller/file_viewer.go
+++ b/webcontroller/file_viewer.go
@@ -78,8 +78,8 @@ func (vd *viewerData) adType(files []pixelapi.ListFile) {
adMavenFloat = 3
// Popunders
- clickAduPopup = 1
- propellerPopup = 2
+ // clickAduPopup = 1
+ // propellerPopup = 2
)
// Intn returns a number up to n, but never n itself. So to get a random 0
diff --git a/webcontroller/misc.go b/webcontroller/misc.go
index dc35fdc..693a8cd 100644
--- a/webcontroller/misc.go
+++ b/webcontroller/misc.go
@@ -44,7 +44,7 @@ func (wc *WebController) serveShareXConfig(w http.ResponseWriter, r *http.Reques
)),
)))
} else {
- w.Write([]byte(fmt.Sprintf(
+ w.Write([]byte(
`{
"Version": "12.4.1",
"DestinationType": "ImageUploader, TextUploader, FileUploader",
@@ -56,6 +56,6 @@ func (wc *WebController) serveShareXConfig(w http.ResponseWriter, r *http.Reques
"ThumbnailURL": "https://pixeldrain.com/api/file/$json:id$/thumbnail"
}
`,
- )))
+ ))
}
}
diff --git a/webcontroller/templates.go b/webcontroller/templates.go
index 0b80b61..3615da4 100644
--- a/webcontroller/templates.go
+++ b/webcontroller/templates.go
@@ -52,7 +52,7 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
APIEndpoint: template.URL(wc.apiURLExternal),
// Use the user's IP address for making requests
- PixelAPI: wc.api.RealIP(util.RemoteAddress(r)),
+ PixelAPI: wc.api.RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent()),
Hostname: template.HTML(wc.hostname),
URLQuery: r.URL.Query(),
@@ -70,7 +70,7 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
if err.Error() == "authentication_required" || err.Error() == "authentication_failed" {
// Disable API authentication
- t.PixelAPI = wc.api.RealIP(util.RemoteAddress(r))
+ t.PixelAPI = wc.api.RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent())
// Remove the authentication cookie
log.Debug("Deleting invalid API key")
@@ -163,6 +163,9 @@ func (tm *TemplateManager) ParseTemplates(silent bool) {
// Parse static resources
var file []byte
if err = filepath.Walk(tm.resourceDir+"/include", func(path string, f os.FileInfo, err error) error {
+ if err != nil {
+ return fmt.Errorf("walk err: %w", err)
+ }
if f == nil || f.IsDir() {
return nil
}
diff --git a/webcontroller/web_controller.go b/webcontroller/web_controller.go
index f5ee60e..94050f8 100644
--- a/webcontroller/web_controller.go
+++ b/webcontroller/web_controller.go
@@ -159,7 +159,8 @@ func New(
{PST, "password_reset" /* */, wc.serveForm(wc.passwordResetForm, handlerOpts{NoEmbed: true})},
{GET, "logout" /* */, wc.serveTemplate("logout", handlerOpts{Auth: true, NoEmbed: true})},
{PST, "logout" /* */, wc.serveLogout},
- {GET, "user" /* */, wc.serveTemplate("user_home", handlerOpts{Auth: true})},
+ {GET, "user_old" /* */, wc.serveTemplate("user_home", handlerOpts{Auth: true})},
+ {GET, "user" /* */, wc.serveTemplate("user_home_svelte", handlerOpts{Auth: true})},
{GET, "user/files" /* */, wc.serveTemplate("user_files", handlerOpts{Auth: true})},
{GET, "user/lists" /* */, wc.serveTemplate("user_lists", handlerOpts{Auth: true})},
{GET, "user/buckets" /* */, wc.serveTemplate("user_buckets", handlerOpts{Auth: true})},
@@ -168,8 +169,9 @@ func New(
{GET, "user/export/lists" /**/, wc.serveUserExportLists},
// User account settings
- {GET, "user/settings" /* */, wc.serveUserSettings},
- {PST, "user/settings" /* */, wc.serveUserSettings},
+ {GET, "user/settings" /* */, wc.serveTemplate("user_home_svelte", handlerOpts{Auth: true})},
+ {GET, "user/settings_old" /* */, wc.serveUserSettings},
+ {PST, "user/settings_old" /* */, wc.serveUserSettings},
{GET, "user/confirm_email" /* */, wc.serveEmailConfirm},
{GET, "user/password_reset_confirm" /**/, wc.serveForm(wc.passwordResetConfirmForm, handlerOpts{NoEmbed: true})},
{PST, "user/password_reset_confirm" /**/, wc.serveForm(wc.passwordResetConfirmForm, handlerOpts{NoEmbed: true})},