Use generated download link element instead of iframe for downloading
This commit is contained in:
@@ -4,15 +4,16 @@ import Modal from "../util/Modal.svelte"
|
|||||||
|
|
||||||
export let file = {
|
export let file = {
|
||||||
id: "",
|
id: "",
|
||||||
|
name: "",
|
||||||
availability: "",
|
availability: "",
|
||||||
download_href: "",
|
download_href: "",
|
||||||
}
|
}
|
||||||
export let list = {
|
export let list = {
|
||||||
id: "",
|
id: "",
|
||||||
|
title: "",
|
||||||
download_href: "",
|
download_href: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
let download_frame
|
|
||||||
let load_captcha_script = false
|
let load_captcha_script = false
|
||||||
let download_captcha_window
|
let download_captcha_window
|
||||||
let captcha_type = "" // rate_limit or malware
|
let captcha_type = "" // rate_limit or malware
|
||||||
@@ -24,13 +25,13 @@ let error_code = ""
|
|||||||
let error_message = ""
|
let error_message = ""
|
||||||
export const download_file = () => {
|
export const download_file = () => {
|
||||||
if (!window.viewer_data.captcha_key) {
|
if (!window.viewer_data.captcha_key) {
|
||||||
console.debug("Server doesn't support captcha, starting download")
|
console.debug("Server doesn't support captcha, starting download", file.download_href)
|
||||||
download_frame.src = file.download_href
|
download(file.download_href, file.name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (file.availability === "") {
|
if (file.availability === "") {
|
||||||
console.debug("File is available, starting download")
|
console.debug("File is available, starting download", file.download_href)
|
||||||
download_frame.src = file.download_href
|
download(file.download_href, file.name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!file.availability.endsWith("_captcha_required")) {
|
if (!file.availability.endsWith("_captcha_required")) {
|
||||||
@@ -47,7 +48,8 @@ export const download_file = () => {
|
|||||||
// we trigger the download using the captcha token Google provided us with
|
// we trigger the download using the captcha token Google provided us with
|
||||||
let captcha_complete_callback = token => {
|
let captcha_complete_callback = token => {
|
||||||
// Download the file using the recaptcha token
|
// Download the file using the recaptcha token
|
||||||
download_frame.src = file.download_href + "&recaptcha_response=" + token
|
console.debug("Captcha validation successful, starting download", file.download_href)
|
||||||
|
download(file.download_href + "&recaptcha_response=" + token, file.name)
|
||||||
download_captcha_window.hide()
|
download_captcha_window.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,9 +93,17 @@ export const download_file = () => {
|
|||||||
}
|
}
|
||||||
export const download_list = () => {
|
export const download_list = () => {
|
||||||
if (list.id !== "") {
|
if (list.id !== "") {
|
||||||
download_frame.src = list.download_href
|
download(list.download_href, list.title+".zip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const download = (href, file_name) => {
|
||||||
|
let a = document.createElement("a")
|
||||||
|
a.href = href
|
||||||
|
a.download = file_name
|
||||||
|
a.click()
|
||||||
|
a.remove()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -102,7 +112,6 @@ export const download_list = () => {
|
|||||||
{/if}
|
{/if}
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<iframe class="download_frame" bind:this={download_frame} title="File download frame"></iframe>
|
|
||||||
<Modal bind:this={download_captcha_window} title={captcha_window_title} width="500px">
|
<Modal bind:this={download_captcha_window} title={captcha_window_title} width="500px">
|
||||||
{#if captcha_type === "rate_limit"}
|
{#if captcha_type === "rate_limit"}
|
||||||
<p class="indent">
|
<p class="indent">
|
||||||
@@ -143,12 +152,6 @@ export const download_list = () => {
|
|||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.download_frame {
|
|
||||||
position: absolute;
|
|
||||||
display: none;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
}
|
|
||||||
.captcha_container {
|
.captcha_container {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { formatDataVolume, formatThousands } from "../util/Formatting.svelte"
|
import { formatDataVolume, formatThousands } from "../util/Formatting.svelte"
|
||||||
import { set_file, stats } from "../lib/StatsSocket.js"
|
import { set_file, stats } from "../lib/StatsSocket.mjs"
|
||||||
|
|
||||||
export let file = {
|
export let file = {
|
||||||
id: "",
|
id: "",
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import { formatDataVolume } from "../util/Formatting.svelte";
|
import { formatDataVolume } from "../util/Formatting.svelte";
|
||||||
import { stats } from "../lib/StatsSocket.js"
|
import { stats } from "../lib/StatsSocket.mjs"
|
||||||
|
|
||||||
let percent = 0
|
let percent = 0
|
||||||
let title = ""
|
let title = ""
|
||||||
$: {
|
$: {
|
||||||
|
if ($stats.limits_init === true) {
|
||||||
if ($stats.limits.transfer_limit === 0) {
|
if ($stats.limits.transfer_limit === 0) {
|
||||||
percent = 0 // Avoid division by 0
|
percent = 0 // Avoid division by 0
|
||||||
} else if ($stats.limits.transfer_limit_used / $stats.limits.transfer_limit > 1) {
|
} else if ($stats.limits.transfer_limit_used / $stats.limits.transfer_limit > 1) {
|
||||||
@@ -18,6 +19,7 @@ $: {
|
|||||||
" of " +
|
" of " +
|
||||||
formatDataVolume($stats.limits.transfer_limit, 3);
|
formatDataVolume($stats.limits.transfer_limit, 3);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Always show the outer bar to prevent layout shift -->
|
<!-- Always show the outer bar to prevent layout shift -->
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
import { formatDataVolume } from "../../util/Formatting.svelte";
|
import { formatDataVolume } from "../../util/Formatting.svelte";
|
||||||
import TextBlock from "../../layout/TextBlock.svelte"
|
import TextBlock from "../../layout/TextBlock.svelte"
|
||||||
import ProgressBar from "../../util/ProgressBar.svelte";
|
import ProgressBar from "../../util/ProgressBar.svelte";
|
||||||
import { stats } from "../../lib/StatsSocket.js"
|
import { stats } from "../../lib/StatsSocket.mjs"
|
||||||
|
|
||||||
export let file = {
|
export let file = {
|
||||||
size: 0,
|
size: 0,
|
||||||
|
@@ -11,7 +11,7 @@ import Abuse from "./Abuse.svelte";
|
|||||||
import { file_type } from "../FileUtilities.svelte";
|
import { file_type } from "../FileUtilities.svelte";
|
||||||
import RateLimit from "./RateLimit.svelte";
|
import RateLimit from "./RateLimit.svelte";
|
||||||
import Torrent from "./Torrent.svelte";
|
import Torrent from "./Torrent.svelte";
|
||||||
import { stats } from "../../lib/StatsSocket.js"
|
import { stats } from "../../lib/StatsSocket.mjs"
|
||||||
import Zip from "./Zip.svelte";
|
import Zip from "./Zip.svelte";
|
||||||
import SlowDown from "../../layout/SlowDown.svelte";
|
import SlowDown from "../../layout/SlowDown.svelte";
|
||||||
import TextBlock from "../../layout/TextBlock.svelte";
|
import TextBlock from "../../layout/TextBlock.svelte";
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import { formatDataVolume } from "../../util/Formatting.svelte";
|
import { formatDataVolume } from "../../util/Formatting.svelte";
|
||||||
import { stats } from "../../lib/StatsSocket.js"
|
import { stats } from "../../lib/StatsSocket.mjs"
|
||||||
import IconBlock from "../../layout/IconBlock.svelte";
|
import IconBlock from "../../layout/IconBlock.svelte";
|
||||||
import TextBlock from "../../layout/TextBlock.svelte"
|
import TextBlock from "../../layout/TextBlock.svelte"
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
@@ -12,7 +12,7 @@ import Menu from './Menu.svelte';
|
|||||||
import { FSNavigator } from "./FSNavigator"
|
import { FSNavigator } from "./FSNavigator"
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
import TransferLimit from '../file_viewer/TransferLimit.svelte';
|
import TransferLimit from '../file_viewer/TransferLimit.svelte';
|
||||||
import { stats } from "../lib/StatsSocket.js"
|
import { stats } from "../lib/StatsSocket.mjs"
|
||||||
import { css_from_path } from './edit_window/Branding';
|
import { css_from_path } from './edit_window/Branding';
|
||||||
import AffiliatePrompt from '../user_home/AffiliatePrompt.svelte';
|
import AffiliatePrompt from '../user_home/AffiliatePrompt.svelte';
|
||||||
|
|
||||||
@@ -20,7 +20,6 @@ let file_viewer
|
|||||||
let file_preview
|
let file_preview
|
||||||
let toolbar
|
let toolbar
|
||||||
let upload_widget
|
let upload_widget
|
||||||
let download_frame
|
|
||||||
let details_visible = false
|
let details_visible = false
|
||||||
let edit_window
|
let edit_window
|
||||||
let edit_visible = false
|
let edit_visible = false
|
||||||
@@ -128,11 +127,18 @@ const keydown = e => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const download = () => {
|
const download = () => {
|
||||||
|
let a = document.createElement("a")
|
||||||
|
|
||||||
if (nav.base.type === "file") {
|
if (nav.base.type === "file") {
|
||||||
download_frame.src = fs_path_url(nav.base.path) + "?attach"
|
a.href = fs_path_url(nav.base.path) + "?attach"
|
||||||
|
a.download = nav.base.name
|
||||||
} else if (nav.base.type === "dir") {
|
} else if (nav.base.type === "dir") {
|
||||||
download_frame.src = fs_path_url(nav.base.path) + "?bulk_download"
|
a.href = fs_path_url(nav.base.path) + "?bulk_download"
|
||||||
|
a.download = nav.base.name+".zip"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.click()
|
||||||
|
a.remove()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -184,13 +190,6 @@ const download = () => {
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- This frame will load the download URL when a download button is pressed -->
|
|
||||||
<iframe
|
|
||||||
bind:this={download_frame}
|
|
||||||
title="Frame for downloading files"
|
|
||||||
style="display: none; width: 1px; height: 1px;">
|
|
||||||
</iframe>
|
|
||||||
|
|
||||||
<DetailsWindow nav={nav} bind:visible={details_visible} />
|
<DetailsWindow nav={nav} bind:visible={details_visible} />
|
||||||
|
|
||||||
<EditWindow nav={nav} bind:this={edit_window} bind:visible={edit_visible} />
|
<EditWindow nav={nav} bind:this={edit_window} bind:visible={edit_visible} />
|
||||||
|
@@ -12,7 +12,7 @@ import Video from "./Video.svelte";
|
|||||||
import Torrent from "./Torrent.svelte";
|
import Torrent from "./Torrent.svelte";
|
||||||
import Zip from "./Zip.svelte";
|
import Zip from "./Zip.svelte";
|
||||||
import CustomBanner from "./CustomBanner.svelte";
|
import CustomBanner from "./CustomBanner.svelte";
|
||||||
import { stats } from "../../lib/StatsSocket.js"
|
import { stats } from "../../lib/StatsSocket.mjs"
|
||||||
import SlowDown from "../../layout/SlowDown.svelte";
|
import SlowDown from "../../layout/SlowDown.svelte";
|
||||||
|
|
||||||
export let nav
|
export let nav
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import { formatDataVolume, formatDuration } from "../util/Formatting.svelte";
|
import { formatDataVolume, formatDuration } from "../util/Formatting.svelte";
|
||||||
import { stats } from "../lib/StatsSocket.js"
|
import { stats } from "../lib/StatsSocket.mjs"
|
||||||
import TextBlock from "./TextBlock.svelte"
|
import TextBlock from "./TextBlock.svelte"
|
||||||
import IconBlock from "./IconBlock.svelte";
|
import IconBlock from "./IconBlock.svelte";
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
@@ -1,25 +1,39 @@
|
|||||||
import { readable } from "svelte/store";
|
import { readable } from "svelte/store";
|
||||||
|
|
||||||
let results = {
|
type SocketResults = {
|
||||||
connected: false,
|
connected: boolean,
|
||||||
file_stats_init: false,
|
file_stats_init: boolean,
|
||||||
file_stats: {
|
file_stats: FileStats
|
||||||
views: 0,
|
limits_init: boolean,
|
||||||
downloads: 0,
|
limits: Limits,
|
||||||
bandwidth: 0,
|
|
||||||
bandwidth_paid: 0,
|
|
||||||
},
|
|
||||||
limits_init: false,
|
|
||||||
limits: {
|
|
||||||
server_overload: false,
|
|
||||||
speed_limit: 0,
|
|
||||||
download_limit: 0,
|
|
||||||
download_limit_used: 0,
|
|
||||||
transfer_limit: 0,
|
|
||||||
transfer_limit_used: 0,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FileStats = {
|
||||||
|
views: number,
|
||||||
|
downloads: number,
|
||||||
|
bandwidth: number,
|
||||||
|
bandwidth_paid: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Limits = {
|
||||||
|
server_overload: boolean,
|
||||||
|
speed_limit: number,
|
||||||
|
download_limit: number,
|
||||||
|
download_limit_used: number,
|
||||||
|
transfer_limit: number,
|
||||||
|
transfer_limit_used: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
type SocketCommand = {
|
||||||
|
type: string,
|
||||||
|
data?: Object,
|
||||||
|
}
|
||||||
|
|
||||||
|
let results: SocketResults = {
|
||||||
|
file_stats: {} as FileStats,
|
||||||
|
limits: {} as Limits,
|
||||||
|
} as SocketResults
|
||||||
|
|
||||||
export const stats = readable(
|
export const stats = readable(
|
||||||
results,
|
results,
|
||||||
(set) => {
|
(set) => {
|
||||||
@@ -28,24 +42,24 @@ export const stats = readable(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let socket = null
|
let socket: WebSocket = null
|
||||||
const start_sock = (set_func) => {
|
const start_sock = (set_func: (value: SocketResults) => void) => {
|
||||||
if (socket !== null) {
|
if (socket !== null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("initializing stats socket")
|
console.log("Initializing stats socket")
|
||||||
socket = new WebSocket(location.origin.replace(/^http/, 'ws') + "/api/file_stats")
|
socket = new WebSocket(location.origin.replace(/^http/, 'ws') + "/api/file_stats")
|
||||||
|
|
||||||
socket.onopen = () => {
|
socket.onopen = () => {
|
||||||
results.connected = true
|
results.connected = true
|
||||||
set_func(results)
|
// set_func(results)
|
||||||
|
|
||||||
// Subscribe to the rate limit feed. This will also process any queued
|
// Subscribe to the rate limit feed. This will also process any queued
|
||||||
// commands built up while the socket was down
|
// commands built up while the socket was down
|
||||||
send_cmd({ type: "limits" })
|
send_cmd({ type: "limits" })
|
||||||
}
|
}
|
||||||
socket.onmessage = msg => {
|
socket.onmessage = (msg: MessageEvent) => {
|
||||||
let j = JSON.parse(msg.data)
|
let j = JSON.parse(msg.data)
|
||||||
console.debug("WS update", j)
|
console.debug("WS update", j)
|
||||||
|
|
||||||
@@ -61,18 +75,19 @@ const start_sock = (set_func) => {
|
|||||||
console.error("Unknown ws message type", j.type, "data", msg.data)
|
console.error("Unknown ws message type", j.type, "data", msg.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.onerror = err => {
|
socket.onerror = (err: Event) => {
|
||||||
console.error("socket error", err)
|
console.error("Stats socket error", err)
|
||||||
stop_sock(set_func)
|
stop_sock(set_func)
|
||||||
window.setTimeout(() => start_sock(set_func), 2000)
|
window.setTimeout(() => start_sock(set_func), 2000)
|
||||||
}
|
}
|
||||||
socket.onclose = () => {
|
socket.onclose = (e: CloseEvent) => {
|
||||||
|
console.debug("Stats socket close", e)
|
||||||
stop_sock(set_func)
|
stop_sock(set_func)
|
||||||
window.setTimeout(() => start_sock(set_func), 2000)
|
window.setTimeout(() => start_sock(set_func), 2000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const stop_sock = (set_func) => {
|
const stop_sock = (set_func: (value: SocketResults) => void) => {
|
||||||
if (socket === null) {
|
if (socket === null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -92,7 +107,8 @@ const stop_sock = (set_func) => {
|
|||||||
set_func(results)
|
set_func(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const set_file = file_id => {
|
|
||||||
|
export const set_file = (file_id: string) => {
|
||||||
send_cmd({
|
send_cmd({
|
||||||
type: "file_stats",
|
type: "file_stats",
|
||||||
data: { file_id: file_id },
|
data: { file_id: file_id },
|
||||||
@@ -100,7 +116,7 @@ export const set_file = file_id => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let queued_commands = []
|
let queued_commands = []
|
||||||
const send_cmd = cmd => {
|
const send_cmd = (cmd: SocketCommand) => {
|
||||||
if (socket !== null && socket.readyState === WebSocket.OPEN) {
|
if (socket !== null && socket.readyState === WebSocket.OPEN) {
|
||||||
|
|
||||||
// First empty the queue
|
// First empty the queue
|
Reference in New Issue
Block a user