diff --git a/res/template/account/user_home.html b/res/template/account/user_home.html index 43ccf41..3471dad 100644 --- a/res/template/account/user_home.html +++ b/res/template/account/user_home.html @@ -1,12 +1,12 @@ {{define "user_home"}} - {{template "meta_tags" .User.Username}} - {{template "user_style" .}} + {{template "meta_tags" .User.Username }} + {{template "user_style" . }} + {{template "user_style_js" . }} diff --git a/res/template/admin.html b/res/template/admin.html index 7903a7f..cd0677d 100644 --- a/res/template/admin.html +++ b/res/template/admin.html @@ -5,10 +5,10 @@ {{template "meta_tags" "Administrator panel"}} {{template "user_style" .}} + {{template "user_style_js" . }} diff --git a/res/template/advertisements.html b/res/template/advertisements.html index 4761d20..fc53760 100644 --- a/res/template/advertisements.html +++ b/res/template/advertisements.html @@ -1,3 +1,11 @@ +{{ define "ad_headers" }} + {{ if eq .Other.AdBannerType 3 }} + + {{ end }} +{{ end }} + {{ define "banner_ads"}} {{ if eq .Other.AdBannerType 1 }} @@ -28,10 +36,8 @@
{{else if eq .Other.AdBannerType 3}} - - - - + +
{{else if eq .Other.AdBannerType 4}} diff --git a/res/template/file_viewer.html b/res/template/file_viewer.html index 5d6b253..dc98902 100644 --- a/res/template/file_viewer.html +++ b/res/template/file_viewer.html @@ -26,6 +26,8 @@ {{ template `viewer.css` }} {{ template `modal.css` }} + + {{ template `ad_headers` . }} diff --git a/res/template/file_viewer_svelte.html b/res/template/file_viewer_svelte.html index 5f0f280..4b8fc65 100644 --- a/res/template/file_viewer_svelte.html +++ b/res/template/file_viewer_svelte.html @@ -8,6 +8,7 @@ {{ template "opengraph" .OGData }} {{ template "user_style" . }} + {{ template "user_style_js" . }} @@ -23,7 +24,7 @@ diff --git a/svelte/src/file_viewer.js b/svelte/src/file_viewer.js new file mode 100644 index 0000000..e6e97d0 --- /dev/null +++ b/svelte/src/file_viewer.js @@ -0,0 +1,8 @@ +import App from './file_viewer/FileViewer.svelte'; + +const app = new App({ + target: document.getElementById("body"), + props: {} +}); + +export default app; diff --git a/svelte/src/file_viewer/DetailsWindow.svelte b/svelte/src/file_viewer/DetailsWindow.svelte new file mode 100644 index 0000000..e0e3064 --- /dev/null +++ b/svelte/src/file_viewer/DetailsWindow.svelte @@ -0,0 +1,134 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name{file.name}
URL{domain_url()}/u/{file.id}
Mime Type{file.mime_type}
ID{file.id}
Size{formatDataVolume(file.size, 4)} ( {formatThousands(file.size)} B )
Bandwidth{formatDataVolume(file.bandwidth_used, 4)} ( {formatThousands(file.bandwidth_used)} B )
Unique downloads{formatThousands(file.downloads)}
+ The unique download counter only counts downloads once per IP + address. So this number shows how many individual people have + attempted to download the file. The download counter on the + toolbar on the other hand shows how many real downloads the file + has had. Real downloads are counted by dividing the total + bandwidth usage by the size of the file. +
Upload Date{formatDate(file.date_upload, true, true, true)}
Description{file.description}
+ +

Downloads

+ +

Views

+ + +

+ Charts rendered by the amazing Chart.js. +

+ +

About

+ Pixeldrain is a file sharing platform. + Visit the home page for more information. + +

Keyboard Controls

+ + + + + + + + + + + +
File Shortcuts
c = Copy URL of this page
i = Toggle details window (this window) (info)
s = Download the file you are currently viewing (save)
q = Close the window (quit)
List Shortcuts
a or ← = View previous item in list
d or → = View next item in list
r = Toggle shuffle (random)
SHIFT + s = Download all the files in the list as a zip archive
+
diff --git a/svelte/src/file_viewer/FilePreview.svelte b/svelte/src/file_viewer/FilePreview.svelte new file mode 100644 index 0000000..e0973e7 --- /dev/null +++ b/svelte/src/file_viewer/FilePreview.svelte @@ -0,0 +1,101 @@ + + +
+ {#if file_type === "loading"} +
+ +
+ {:else if file_type === "abuse"} + + {:else if file_type === "image"} + + {:else if file_type === "video"} + + {:else if file_type === "audio"} + + {:else if file_type === "pdf"} + + {:else if file_type === "text"} + + {:else if file_type === "file"} + + {/if} +
+ + diff --git a/svelte/src/file_viewer/FileViewer.svelte b/svelte/src/file_viewer/FileViewer.svelte new file mode 100644 index 0000000..20be2cd --- /dev/null +++ b/svelte/src/file_viewer/FileViewer.svelte @@ -0,0 +1,618 @@ + + + + +
+
+ + + + +
+
{current_list.title}
+
{current_file.name}
+
+ {#if embedded && supports_fullscreen} + + {/if} +
+ + {#if is_list} + { open_file(e.detail) }}> + {/if} + +
+
+
Views
+
N/A
+
Downloads
+
N/A
+
Size
+
N/A
+ +
+ + {#if is_list} + + {/if} + + + + {#if is_list} + + {/if} + +
+ + + + +
+
+ +
+ Share on:
+ + + + + +
+ +
+ { if (list_navigator) { list_navigator.prev() }}} + on:next={() => { if (list_navigator) { list_navigator.next() }}}> + +
+ +
+ +
+
+ + + +
+ +
+
+ Thank you for supporting pixeldrain! +
+
+ + {details_visible = e.detail}} title="File details" width="1200px"> + + + {qr_visible = e.detail}} title="QR code"> + Hi! + + {edit_visible = e.detail}} title={"Editing "+current_file.name}> + Hi! + + {embed_visible = e.detail}} title="Embed file"> + Hi! + + {report_visible = e.detail}} title="Report abuse"> + Hi! + +
+ + + diff --git a/svelte/src/file_viewer/ListNavigator.svelte b/svelte/src/file_viewer/ListNavigator.svelte new file mode 100644 index 0000000..e883ae7 --- /dev/null +++ b/svelte/src/file_viewer/ListNavigator.svelte @@ -0,0 +1,120 @@ + + +
+ {#each files as file, index} +
{ set_item(index) }}> + {file.name} + {file.name} +
+ {/each} +
+ + diff --git a/svelte/src/file_viewer/viewers/Abuse.svelte b/svelte/src/file_viewer/viewers/Abuse.svelte new file mode 100644 index 0000000..8fc5542 --- /dev/null +++ b/svelte/src/file_viewer/viewers/Abuse.svelte @@ -0,0 +1,29 @@ + + +
+

Unavailable for legal reasons

+

+ This file has received an abuse report and was taken down. +

+

+ Type of abuse: {file.abuse_type}. Reporter: {file.abuse_reporter_name}. +

+
+ + diff --git a/svelte/src/file_viewer/viewers/Audio.svelte b/svelte/src/file_viewer/viewers/Audio.svelte new file mode 100644 index 0000000..f8947db --- /dev/null +++ b/svelte/src/file_viewer/viewers/Audio.svelte @@ -0,0 +1,106 @@ + + +
+ + + + + +

+ + {#if !audio_reload} + + + {/if} +
+ + diff --git a/svelte/src/file_viewer/viewers/File.svelte b/svelte/src/file_viewer/viewers/File.svelte new file mode 100644 index 0000000..16a2275 --- /dev/null +++ b/svelte/src/file_viewer/viewers/File.svelte @@ -0,0 +1,47 @@ + + +
+

You are viewing a file on pixeldrain

+ File icon +
+ Name: {file.name}
+ Type: {file.mime_type}
+ No preview is available for this file type. Download to view it locally. +
+ +
+
+ + diff --git a/svelte/src/file_viewer/viewers/Image.svelte b/svelte/src/file_viewer/viewers/Image.svelte new file mode 100644 index 0000000..887150f --- /dev/null +++ b/svelte/src/file_viewer/viewers/Image.svelte @@ -0,0 +1,91 @@ + + + + +
+ {zoom = !zoom}} + on:doubletap={() => {zoom = !zoom}} + on:mousedown={mousedown} + class="image" class:zoom + src={file.get_href} + alt={file.name} /> +
+ + diff --git a/svelte/src/file_viewer/viewers/PDF.svelte b/svelte/src/file_viewer/viewers/PDF.svelte new file mode 100644 index 0000000..40ce18d --- /dev/null +++ b/svelte/src/file_viewer/viewers/PDF.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/svelte/src/file_viewer/viewers/Text.svelte b/svelte/src/file_viewer/viewers/Text.svelte new file mode 100644 index 0000000..9347e89 --- /dev/null +++ b/svelte/src/file_viewer/viewers/Text.svelte @@ -0,0 +1,126 @@ + + + +
+ {#if text_type === "markdown"} +
+ Loading... +
+ {:else if text_type === "text"} +
+			Loading...
+		
+ {:else if text_type === "code"} +
+			Loading...
+		
+ {/if} +
+ + diff --git a/svelte/src/file_viewer/viewers/Video.svelte b/svelte/src/file_viewer/viewers/Video.svelte new file mode 100644 index 0000000..be0c0d1 --- /dev/null +++ b/svelte/src/file_viewer/viewers/Video.svelte @@ -0,0 +1,106 @@ + + +
+ {#if file.allow_video_player} + {#if !video_reload} + + + {/if} + {:else} +

This is a video file on pixeldrain

+ Video icon +
+ 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. +
+ + upgrade Upgrade to Pro + + +
+ {/if} +
+ + diff --git a/svelte/src/filesystem/Toolbar.svelte b/svelte/src/filesystem/Toolbar.svelte deleted file mode 100644 index 7eb173f..0000000 --- a/svelte/src/filesystem/Toolbar.svelte +++ /dev/null @@ -1,111 +0,0 @@ - - -
-
Views
-
{formatThousands(file.views)}
-
Downloads
-
{formatThousands(file.downloads)}
-
Size
-
{formatDataVolume(file.size)}
- - - - - - - - -
- - diff --git a/svelte/src/user_file_manager/FileManager.svelte b/svelte/src/user_file_manager/FileManager.svelte index a56b32c..c159368 100644 --- a/svelte/src/user_file_manager/FileManager.svelte +++ b/svelte/src/user_file_manager/FileManager.svelte @@ -271,8 +271,7 @@ onMount(() => { bind:this={help_modal} title="File manager help" width="600px" - on:shown={() => help_modal_visible = true} - on:hidden={() => help_modal_visible = false} + on:is_visible={e => {help_modal_visible = e.detail}} >

In the file manager you can see the files you have uploaded and the diff --git a/svelte/src/util/Chart.svelte b/svelte/src/util/Chart.svelte index dcc8b6b..8d69d98 100644 --- a/svelte/src/util/Chart.svelte +++ b/svelte/src/util/Chart.svelte @@ -35,7 +35,7 @@ onMount(() => { datasets: [ { label: label, - backgroundColor: window.highlight_color, + backgroundColor: "#"+window.style.highlightColor, borderWidth: 0, lineTension: 0, fill: true, diff --git a/svelte/src/util/Modal.svelte b/svelte/src/util/Modal.svelte index f99382d..4043840 100644 --- a/svelte/src/util/Modal.svelte +++ b/svelte/src/util/Modal.svelte @@ -22,19 +22,18 @@ const load_modal = modal => { } const dispatch = createEventDispatcher(); -export const show = () => { visible = true; dispatch("shown"); } -export const hide = () => { visible = false; dispatch("hidden"); } -export const toggle = () => { - if (visible) { - hide() - } else { - show() - } + +export const show = () => { set_visible(true) } +export const hide = () => { set_visible(false) } +export const toggle = () => { set_visible(!visible) } +export const set_visible = vis => { + visible = vis + dispatch("is_visible", visible) } const keydown = e => { if (e.key === 'Escape') { - hide(); + set_visible(false); return; } }; diff --git a/svelte/src/util/PixeldrainLogo.svelte b/svelte/src/util/PixeldrainLogo.svelte index cb2d9d9..11a5909 100644 --- a/svelte/src/util/PixeldrainLogo.svelte +++ b/svelte/src/util/PixeldrainLogo.svelte @@ -7,7 +7,6 @@ diff --git a/webcontroller/file_viewer.go b/webcontroller/file_viewer.go index 57641d5..9851d74 100644 --- a/webcontroller/file_viewer.go +++ b/webcontroller/file_viewer.go @@ -56,7 +56,7 @@ func (vd *viewerData) adType(files []pixelapi.ListFile) { none = 0 aAds = 1 patreon = 2 - soulStudio = 3 + adshares = 3 amarulaSolutions = 4 adMaven = 5 adSterra = 6 @@ -76,6 +76,8 @@ func (vd *viewerData) adType(files []pixelapi.ListFile) { // Skyscrapers aAdsSkyscraper = "a-ads" pixfutureSkyscraper = "pixfuture" + adsPlusSkyscraper = "adsplus" + adsharesSkyscraper = "adshares" // Floaters // propellerFloat = 1 @@ -108,10 +110,10 @@ func (vd *viewerData) adType(files []pixelapi.ListFile) { panic(fmt.Errorf("random number generator returned unrecognised number: %d", i)) } - switch i := rand.Intn(4); i { + switch i := rand.Intn(2); i { case 0: vd.AdSkyscraperType = aAdsSkyscraper - case 1, 2, 3: + case 1: vd.AdSkyscraperType = pixfutureSkyscraper default: panic(fmt.Errorf("random number generator returned unrecognised number: %d", i)) diff --git a/webcontroller/file_viewer_svelte.go b/webcontroller/file_viewer_svelte.go new file mode 100644 index 0000000..a2e765e --- /dev/null +++ b/webcontroller/file_viewer_svelte.go @@ -0,0 +1,156 @@ +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"` + AdBannerType string `json:"ad_banner_type"` + AdSkyscraperType string `json:"ad_skyscraper_type"` + AdFloaterType string `json:"ad_floater_type"` + Embedded bool `json:"embedded"` + FileAdsEnabled bool `json:"file_ads_enabled"` + 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 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(), + FileAdsEnabled: files[0].ShowAds, + 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 + } + } + + err = wc.templates.Get().ExecuteTemplate(w, "file_viewer_svelte", 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(), + FileAdsEnabled: list.Files[0].ShowAds, + 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 + } + } + + err = wc.templates.Get().ExecuteTemplate(w, "file_viewer_svelte", templateData) + if err != nil && !strings.Contains(err.Error(), "broken pipe") { + log.Error("Error executing template file_viewer: %s", err) + } +} diff --git a/webcontroller/web_controller.go b/webcontroller/web_controller.go index eaea075..9bc601f 100644 --- a/webcontroller/web_controller.go +++ b/webcontroller/web_controller.go @@ -135,6 +135,8 @@ func New( {GET, "history" /* */, wc.serveTemplate("history_cookies", handlerOpts{})}, {GET, "u/:id" /* */, wc.serveFileViewer}, {GET, "u/:id/preview" /* */, wc.serveFilePreview}, + {GET, "u2/:id" /* */, wc.serveSvelteFile}, + {GET, "l2/:id" /* */, wc.serveSvelteList}, {GET, "l/:id" /* */, wc.serveListViewer}, {GET, "d/*path" /* */, wc.serveDirectory}, {GET, "t" /* */, wc.serveTemplate("text_editor", handlerOpts{})},