diff --git a/go.mod b/go.mod index d5d7d95..f48f61f 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module fornaxian.tech/pixeldrain_web go 1.17 +replace fornaxian.tech/pixeldrain_api_client => ../pixeldrain_api_client + require ( fornaxian.tech/config v0.0.0-20211108212237-6133aed90586 fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640 diff --git a/go.sum b/go.sum index aa1732e..f488720 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,6 @@ fornaxian.tech/config v0.0.0-20211108212237-6133aed90586/go.mod h1:ULIXF4J1DbBw4 fornaxian.tech/log v0.0.0-20190617093801-1c7ce9a7c9b3/go.mod h1:OyWUNsNPlo5AmlOHvJ4s6WcStQw+9rQyBMwmTz0buEM= fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640 h1:UPDxJwLRCfh/cv80UMSanzmZ0jIcfS1mcd0Y06HYuLw= fornaxian.tech/log v0.0.0-20211102185326-552e9b1f8640/go.mod h1:sN82qMToeHhP2u3ehvrcE8y1IudRZJAZO9yG5OBYblo= -fornaxian.tech/pixeldrain_api_client v0.0.0-20220127185304-6a60644d957e h1:/PLg0AMCPx6Uft5oPb70ogK127/oWrRGadPU0kvqRv8= -fornaxian.tech/pixeldrain_api_client v0.0.0-20220127185304-6a60644d957e/go.mod h1:uajB2ofEsefUtxjvs4m7SDyPVRlfrI3qzCSWcud47hY= fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787 h1:9ujI8Qi6+FTL/YW6xQAS9DmWDMerHBe8foQvVD/G/i0= fornaxian.tech/util v0.0.0-20211102152345-9a486dee9787/go.mod h1:FqVgfghmxTGR3l9Zx4MOMeZ9KHjiEFl3s3C0BSTvBwk= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= diff --git a/res/include/style/layout.css b/res/include/style/layout.css index 044f53e..110b4c9 100644 --- a/res/include/style/layout.css +++ b/res/include/style/layout.css @@ -105,7 +105,7 @@ footer { .page_navigation { position: fixed; backface-visibility: hidden; - width: 18em; + width: 17em; height: 100%; left: 0; float: left; @@ -119,7 +119,7 @@ footer { position: absolute; right: 0; height: auto; - left: 18em; + left: 17em; min-width: 300px; display: inline-block; text-align: center; /* Center the header and body */ @@ -131,7 +131,7 @@ footer { padding: 8px; transition: left 0.5s; } -@media (max-width: 1000px) { +@media (max-width: 1200px) { .page_navigation { left: -18em; } @@ -467,7 +467,9 @@ select:disabled , select.disabled { cursor: not-allowed; } button > i, -.button > i { +.button > i, +button > svg, +.button > svg { vertical-align: middle; line-height: 1; } diff --git a/res/static/misc/amogus.opus b/res/static/misc/amogus.opus new file mode 100644 index 0000000..7d6167a Binary files /dev/null and b/res/static/misc/amogus.opus differ diff --git a/res/template/home.html b/res/template/home.html index 5ffb82b..843a679 100644 --- a/res/template/home.html +++ b/res/template/home.html @@ -60,9 +60,9 @@ background-position: center; background-size: cover; text-align: left; - font-size: 1.1em; + font-size: 1.2em; color: #ffffff; - text-shadow: 1px 1px 4px #000000; + text-shadow: 1px 1px 3px #000000; } .feat_table > div > div.round_tl { border-top-left-radius: 0.5em; } @@ -298,10 +298,10 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
180 days file expiry
-
2 TB transfer limit
-
2 TB storage space
+
2 TB transfer limit
+
2 TB storage space
@@ -315,10 +315,16 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
360 days file expiry
-
4 TB transfer limit
-
4 TB storage space
+
4 TB transfer limit
+
4 TB storage space
+
+ File viewer + branding: Set a custom theme and header, + footer and background images on the download pages + for your files +
@@ -332,10 +338,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
8 TB transfer limit
-
8 TB storage space
+
8 TB transfer limit
+
8 TB storage space
+
File viewer branding
@@ -349,10 +356,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
16 TB transfer limit
-
16 TB storage space
+
16 TB transfer limit
+
16 TB storage space
+
File viewer branding
@@ -366,10 +374,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
32 TB transfer limit
-
32 TB storage space
+
32 TB transfer limit
+
32 TB storage space
+
File viewer branding
@@ -385,10 +394,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
48 TB transfer limit
-
48 TB storage space
+
48 TB transfer limit
+
48 TB storage space
+
File viewer branding
@@ -404,10 +414,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
64 TB transfer limit
-
64 TB storage space
+
64 TB transfer limit
+
64 TB storage space
+
File viewer branding
@@ -423,10 +434,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
96 TB transfer limit
-
96 TB storage space
+
96 TB transfer limit
+
96 TB storage space
+
File viewer branding
@@ -442,10 +454,11 @@ {{end}}
-
20 GB max file size
+
20 GB max file size
Files never expire
-
128 TB transfer limit
-
128 TB storage space
+
128 TB transfer limit
+
128 TB storage space
+
File viewer branding
diff --git a/svelte/src/file_viewer/CustomBanner.svelte b/svelte/src/file_viewer/CustomBanner.svelte new file mode 100644 index 0000000..57ab480 --- /dev/null +++ b/svelte/src/file_viewer/CustomBanner.svelte @@ -0,0 +1,22 @@ + + +{#if src} +
+ User-provided banner +
+{/if} + + diff --git a/svelte/src/file_viewer/EmbedWindow.svelte b/svelte/src/file_viewer/EmbedWindow.svelte index 7ba17e4..c145c9b 100644 --- a/svelte/src/file_viewer/EmbedWindow.svelte +++ b/svelte/src/file_viewer/EmbedWindow.svelte @@ -1,4 +1,5 @@ @@ -142,38 +153,8 @@ const example = () => { You can change the pixeldrain theme for your embedded file. Try the available themes here.

-
- - - - - - - - - - -
+ + set_style(e.detail)}> {:else}

Direct link

@@ -201,7 +182,7 @@ const example = () => { Copy HTML {/if} - diff --git a/svelte/src/file_viewer/FilePicker.svelte b/svelte/src/file_viewer/FilePicker.svelte index 8274d2a..2f2b2b8 100644 --- a/svelte/src/file_viewer/FilePicker.svelte +++ b/svelte/src/file_viewer/FilePicker.svelte @@ -5,6 +5,7 @@ import DirectoryElement from "../user_file_manager/DirectoryElement.svelte"; import Modal from "../util/Modal.svelte"; let dispatch = createEventDispatcher() +export let multi_select = true let modal; let directory_element; let input_search; @@ -92,7 +93,7 @@ const keydown = (e) => {

- +
diff --git a/svelte/src/file_viewer/FileViewer.svelte b/svelte/src/file_viewer/FileViewer.svelte index bb56dc1..531e93e 100644 --- a/svelte/src/file_viewer/FileViewer.svelte +++ b/svelte/src/file_viewer/FileViewer.svelte @@ -19,6 +19,7 @@ import Sharebar from "./Sharebar.svelte"; import GalleryView from "./GalleryView.svelte"; import Spinner from "../util/Spinner.svelte"; import Downloader from "./Downloader.svelte"; +import CustomBanner from "./CustomBanner.svelte"; let loading = true let embedded = false @@ -145,6 +146,10 @@ const open_list = l => { // correct file is opened is_list = true + if (l.files.length !== 0) { + apply_customizations(l.files[0]) + } + hash_change() } const hash_change = () => { @@ -200,6 +205,8 @@ const open_file_index = async index => { document.title = file.name+" ~ pixeldrain" } + apply_customizations(file) + // Register a file view fetch(window.api_endpoint + "/file/" + file.id + "/view", { method: "POST", @@ -215,6 +222,30 @@ const toggle_gallery = () => { } } +// Premium page customizations. In the gallery view we will use the +// customizations for the first file in the list, else we simply use the +// selected file. In most cases they are all the same so the user won't notice +// any change +let file_preview_background +let custom_header = "" +let custom_background = "" +let custom_footer = "" +const apply_customizations = file => { + if (file.custom_header) { + custom_header = window.api_endpoint+"/file/"+file.custom_header + } + if (file.custom_footer) { + custom_footer = window.api_endpoint+"/file/"+file.custom_footer + } + + if (file.custom_background) { + custom_background = window.api_endpoint+"/file/"+file.custom_background + file_preview_background.style.backgroundImage = "url('"+custom_background+"')" + } else { + file_preview_background.style.backgroundImage = "" + } +} + let supports_fullscreen = !!document.documentElement.requestFullscreen let fullscreen = false const toggle_fullscreen = () => { @@ -378,6 +409,8 @@ const keyboard_event = evt => { {/if} + +
{#if view === "file"} @@ -523,7 +556,13 @@ const keyboard_event = evt => {
-
+
{#if view === "file"} { {#if ads_enabled} + {:else if custom_footer} + {:else if !window.viewer_data.user_ads_enabled && !embedded}
Thank you for supporting pixeldrain! @@ -660,7 +701,7 @@ const keyboard_event = evt => { height: auto; margin: 0; } -.file_preview { +.file_preview_container { position: absolute; left: 0; right: 0; @@ -676,6 +717,12 @@ const keyboard_event = evt => { box-shadow: inset 2px 2px 10px 2px var(--shadow_color); border-radius: 16px; } +.file_preview_container.toolbar_visible { left: 8em; } +.file_preview_container.skyscraper_visible { right: 160px; } +.file_preview_container.custom_background { + background-size: cover; + background-position: center; +} /* Toolbars */ .toolbar { @@ -692,8 +739,6 @@ const keyboard_event = evt => { z-index: 1; } .toolbar.toolbar_visible { left: 0; } -.file_preview.toolbar_visible { left: 8em; } -.file_preview.skyscraper_visible { right: 160px; } /* Workaround to hide the scrollbar in non webkit browsers, it's really ugly' */ .toolbar > div { diff --git a/svelte/src/file_viewer/GalleryView.svelte b/svelte/src/file_viewer/GalleryView.svelte index a2e3249..058c340 100644 --- a/svelte/src/file_viewer/GalleryView.svelte +++ b/svelte/src/file_viewer/GalleryView.svelte @@ -156,7 +156,7 @@ const drop = (e, index) => { {/if}
- {add_files(e.detail)}}> + {add_files(e.detail)}} multi_select={true}> diff --git a/svelte/src/util/Konami.svelte b/svelte/src/util/Konami.svelte new file mode 100644 index 0000000..8544062 --- /dev/null +++ b/svelte/src/util/Konami.svelte @@ -0,0 +1,31 @@ + + + diff --git a/svelte/src/util/SuccessMessage.svelte b/svelte/src/util/SuccessMessage.svelte new file mode 100644 index 0000000..e371057 --- /dev/null +++ b/svelte/src/util/SuccessMessage.svelte @@ -0,0 +1,18 @@ + + +{#if m} +
+ {m} +
+{/if} diff --git a/svelte/src/util/ThemePicker.svelte b/svelte/src/util/ThemePicker.svelte new file mode 100644 index 0000000..4ad162b --- /dev/null +++ b/svelte/src/util/ThemePicker.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + + + + +
+ + diff --git a/webcontroller/file_viewer.go b/webcontroller/file_viewer.go index a63da8e..a059f70 100644 --- a/webcontroller/file_viewer.go +++ b/webcontroller/file_viewer.go @@ -97,6 +97,8 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request, templateData.Other = vd + fileStyleOverride(templateData, files) + for _, file := range files { if file.AbuseType != "" { w.WriteHeader(http.StatusUnavailableForLegalReasons) @@ -157,6 +159,8 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, } templateData.Other = vd + fileStyleOverride(templateData, list.Files) + for _, file := range list.Files { if file.AbuseType != "" { w.WriteHeader(http.StatusUnavailableForLegalReasons) @@ -175,6 +179,16 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, } } +func fileStyleOverride(td *TemplateData, files []pixelapi.ListFile) { + if len(files) == 0 { + return + } + + if files[0].CustomTheme != "" { + td.setStyle(userStyle(files[0].CustomTheme)) + } +} + // 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. diff --git a/webcontroller/templates.go b/webcontroller/templates.go index 9e0b4f7..ad3de86 100644 --- a/webcontroller/templates.go +++ b/webcontroller/templates.go @@ -21,6 +21,7 @@ import ( // TemplateData is a struct that every template expects when being rendered. In // the field Other you can pass your own template-specific variables. type TemplateData struct { + tpm *TemplateManager Authenticated bool User pixelapi.UserInfo UserAgent string @@ -45,15 +46,18 @@ type TemplateData struct { Form Form } +func (td *TemplateData) setStyle(style pixeldrainStyleSheet) { + td.Style = style + td.UserStyle = template.CSS(style.String()) + td.BackgroundPattern = style.Background(td.tpm.tpl) +} + func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) (t *TemplateData) { - var style = userStyle(r) t = &TemplateData{ - Authenticated: false, - UserAgent: r.UserAgent(), - Style: style, - UserStyle: template.CSS(style.String()), - BackgroundPattern: style.Background(wc.templates.tpl), - APIEndpoint: template.URL(wc.apiURLExternal), + tpm: wc.templates, + Authenticated: false, + UserAgent: r.UserAgent(), + APIEndpoint: template.URL(wc.apiURLExternal), // Use the user's IP address for making requests PixelAPI: wc.api.RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent()), @@ -63,6 +67,8 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) URLQuery: r.URL.Query(), } + t.setStyle(userStyleFromRequest(r)) + // If the user is authenticated we'll indentify him and put the user info // into the templatedata. This is used for putting the username in the menu // and stuff like that diff --git a/webcontroller/user_style.go b/webcontroller/user_style.go index 338b431..8c353ac 100644 --- a/webcontroller/user_style.go +++ b/webcontroller/user_style.go @@ -9,7 +9,7 @@ import ( "time" ) -func userStyle(r *http.Request) (s pixeldrainStyleSheet) { +func userStyleFromRequest(r *http.Request) (s pixeldrainStyleSheet) { // Get the chosen style from the URL var style = r.URL.Query().Get("style") @@ -20,6 +20,10 @@ func userStyle(r *http.Request) (s pixeldrainStyleSheet) { } } + return userStyle(style) +} + +func userStyle(style string) (s pixeldrainStyleSheet) { switch style { case "classic": s = pixeldrainClassicStyle