Remove some event dispatchers
This commit is contained in:
@@ -4,13 +4,16 @@ import Expandable from "util/Expandable.svelte";
|
|||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let { report, ip_report_count } = $props();
|
let {
|
||||||
|
report,
|
||||||
|
ip_report_count
|
||||||
|
} = $props();
|
||||||
let preview = $state(false)
|
let preview = $state(false)
|
||||||
|
|
||||||
let can_grant = $derived(report.status !== "granted")
|
let can_grant = $derived(report.status !== "granted")
|
||||||
let can_reject = $derived(report.status !== "rejected")
|
let can_reject = $derived(report.status !== "rejected")
|
||||||
|
|
||||||
let set_status = async (action, report_type) => {
|
let set_status = async (action: string, report_type: string) => {
|
||||||
dispatch("resolve_report", {action: action, report_type: report_type})
|
dispatch("resolve_report", {action: action, report_type: report_type})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -199,7 +199,7 @@ onDestroy(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<ServerDiagnostics running_since={status.cpu_profile_running_since} on:refresh={() => getStats(lastOrder)}/>
|
<ServerDiagnostics running_since={status.cpu_profile_running_since} refresh={() => getStats(lastOrder)}/>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>Process stats</h3>
|
<h3>Process stats</h3>
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { get_endpoint } from "lib/PixeldrainAPI";
|
import { get_endpoint } from "lib/PixeldrainAPI";
|
||||||
import { createEventDispatcher, onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { formatDuration } from "util/Formatting";
|
import { formatDuration } from "util/Formatting";
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
interface Props {
|
let {
|
||||||
running_since?: string;
|
running_since = "",
|
||||||
}
|
refresh,
|
||||||
|
}: {
|
||||||
let { running_since = "" }: Props = $props();
|
running_since?: string
|
||||||
|
refresh?: () => void
|
||||||
|
} = $props();
|
||||||
|
|
||||||
let profile_running = $derived(running_since != "0001-01-01T00:00:00Z" && running_since != "")
|
let profile_running = $derived(running_since != "0001-01-01T00:00:00Z" && running_since != "")
|
||||||
|
|
||||||
@@ -25,7 +26,9 @@ const start = async () => {
|
|||||||
window.open(get_endpoint()+"/admin/cpu_profile")
|
window.open(get_endpoint()+"/admin/cpu_profile")
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch("refresh")
|
if (refresh !== undefined) {
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let interval: number
|
let interval: number
|
||||||
|
@@ -6,7 +6,7 @@ import Breadcrumbs from "./Breadcrumbs.svelte";
|
|||||||
import DetailsWindow from "./DetailsWindow.svelte";
|
import DetailsWindow from "./DetailsWindow.svelte";
|
||||||
import FilePreview from "./viewers/FilePreview.svelte";
|
import FilePreview from "./viewers/FilePreview.svelte";
|
||||||
import FSUploadWidget from "./upload_widget/FSUploadWidget.svelte";
|
import FSUploadWidget from "./upload_widget/FSUploadWidget.svelte";
|
||||||
import { fs_download, type FSPath } from "lib/FilesystemAPI.svelte";
|
import { type FSPath } from "lib/FilesystemAPI.svelte";
|
||||||
import { FSNavigator } from "./FSNavigator"
|
import { FSNavigator } from "./FSNavigator"
|
||||||
import { css_from_path } from "filesystem/edit_window/Branding";
|
import { css_from_path } from "filesystem/edit_window/Branding";
|
||||||
import AffiliatePrompt from "user_home/AffiliatePrompt.svelte";
|
import AffiliatePrompt from "user_home/AffiliatePrompt.svelte";
|
||||||
@@ -18,6 +18,7 @@ let upload_widget: FSUploadWidget = $state()
|
|||||||
let details_visible = $state(false)
|
let details_visible = $state(false)
|
||||||
let edit_window: EditWindow = $state()
|
let edit_window: EditWindow = $state()
|
||||||
let edit_visible = $state(false)
|
let edit_visible = $state(false)
|
||||||
|
let details_window: DetailsWindow = $state()
|
||||||
|
|
||||||
const nav = $state(new FSNavigator(true))
|
const nav = $state(new FSNavigator(true))
|
||||||
|
|
||||||
@@ -75,16 +76,11 @@ const keydown = (e: KeyboardEvent) => {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "s":
|
case "s":
|
||||||
fs_download(nav.base)
|
nav.base.download()
|
||||||
break;
|
break;
|
||||||
case "r":
|
case "r":
|
||||||
nav.shuffle = !nav.shuffle
|
nav.shuffle = !nav.shuffle
|
||||||
break;
|
break;
|
||||||
case "f": // F fullscreen
|
|
||||||
if (toolbar) {
|
|
||||||
toolbar.toggle_fullscreen()
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "a":
|
case "a":
|
||||||
case "ArrowLeft":
|
case "ArrowLeft":
|
||||||
nav.open_sibling(-1)
|
nav.open_sibling(-1)
|
||||||
@@ -145,9 +141,7 @@ const keydown = (e: KeyboardEvent) => {
|
|||||||
nav={nav}
|
nav={nav}
|
||||||
upload_widget={upload_widget}
|
upload_widget={upload_widget}
|
||||||
edit_window={edit_window}
|
edit_window={edit_window}
|
||||||
on:open_sibling={e => nav.open_sibling(e.detail)}
|
details_window={details_window}
|
||||||
on:download={() => fs_download(nav.base)}
|
|
||||||
on:details={() => details_visible = !details_visible}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -157,11 +151,10 @@ const keydown = (e: KeyboardEvent) => {
|
|||||||
bind:details_visible={details_visible}
|
bind:details_visible={details_visible}
|
||||||
edit_window={edit_window}
|
edit_window={edit_window}
|
||||||
bind:edit_visible={edit_visible}
|
bind:edit_visible={edit_visible}
|
||||||
on:download={() => fs_download(nav.base)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DetailsWindow nav={nav} bind:visible={details_visible} />
|
<DetailsWindow nav={nav} bind:this={details_window} 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} />
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import { copy_text } from "util/Util";
|
import { copy_text } from "util/Util";
|
||||||
import FileStats from "./FileStats.svelte";
|
import FileStats from "./FileStats.svelte";
|
||||||
import type { FSNavigator } from "./FSNavigator";
|
import type { FSNavigator } from "./FSNavigator";
|
||||||
@@ -8,8 +7,6 @@ import { fs_share_url, path_is_shared } from "lib/FilesystemAPI.svelte";
|
|||||||
import ShareDialog from "./ShareDialog.svelte";
|
import ShareDialog from "./ShareDialog.svelte";
|
||||||
import { bookmark_add, bookmark_del, bookmarks_store, is_bookmark } from "lib/Bookmarks";
|
import { bookmark_add, bookmark_del, bookmarks_store, is_bookmark } from "lib/Bookmarks";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
nav = $bindable(),
|
nav = $bindable(),
|
||||||
details_visible = $bindable(false),
|
details_visible = $bindable(false),
|
||||||
@@ -53,7 +50,7 @@ export const copy_link = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button onclick={() => dispatch("download")}>
|
<button onclick={() => $nav.base.download()}>
|
||||||
<i class="icon">save</i>
|
<i class="icon">save</i>
|
||||||
<span>Download</span>
|
<span>Download</span>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -33,12 +33,12 @@ const pick_image = (type: string) => {
|
|||||||
picking = type
|
picking = type
|
||||||
picker.open(file.path)
|
picker.open(file.path)
|
||||||
}
|
}
|
||||||
const handle_picker = async (e: CustomEvent<FSNode[]>) => {
|
const handle_picker = async (nodes: FSNode[]) => {
|
||||||
if (e.detail.length !== 1) {
|
if (nodes.length !== 1) {
|
||||||
alert("Please select one file")
|
alert("Please select one file")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let f = e.detail[0]
|
let f = nodes[0]
|
||||||
|
|
||||||
if (fs_node_type(f) !== "image") {
|
if (fs_node_type(f) !== "image") {
|
||||||
alert("Please select an image file")
|
alert("Please select an image file")
|
||||||
@@ -52,7 +52,7 @@ const handle_picker = async (e: CustomEvent<FSNode[]>) => {
|
|||||||
if (!f.is_shared()) {
|
if (!f.is_shared()) {
|
||||||
try {
|
try {
|
||||||
f = await fs_update(
|
f = await fs_update(
|
||||||
e.detail[0].path,
|
nodes[0].path,
|
||||||
{link_permissions: {read: true} as FSPermissions},
|
{link_permissions: {read: true} as FSPermissions},
|
||||||
)
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -186,7 +186,7 @@ run(() => {
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<FilePicker bind:this={picker} on:files={handle_picker}/>
|
<FilePicker bind:this={picker} callback={handle_picker}/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
input[type="color"] {
|
input[type="color"] {
|
||||||
|
@@ -4,7 +4,7 @@ import type { FSNavigator } from "filesystem/FSNavigator";
|
|||||||
import Button from "layout/Button.svelte";
|
import Button from "layout/Button.svelte";
|
||||||
import Dialog from "layout/Dialog.svelte";
|
import Dialog from "layout/Dialog.svelte";
|
||||||
import { bookmark_add, bookmark_del, bookmarks_store, is_bookmark } from "lib/Bookmarks";
|
import { bookmark_add, bookmark_del, bookmarks_store, is_bookmark } from "lib/Bookmarks";
|
||||||
import { fs_delete, fs_download, type FSNode } from "lib/FilesystemAPI.svelte";
|
import { fs_delete, type FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import { loading_finish, loading_start } from "lib/Loading";
|
import { loading_finish, loading_start } from "lib/Loading";
|
||||||
import { tick } from "svelte";
|
import { tick } from "svelte";
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ const delete_node = async () => {
|
|||||||
|
|
||||||
<Dialog bind:this={dialog}>
|
<Dialog bind:this={dialog}>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<Button click={() => {dialog.close(); fs_download(node)}} icon="save" label="Download"/>
|
<Button click={() => {dialog.close(); node.download()}} icon="save" label="Download"/>
|
||||||
{#if node !== null && is_bookmark($bookmarks_store, node.id)}
|
{#if node !== null && is_bookmark($bookmarks_store, node.id)}
|
||||||
<Button click={() => {dialog.close(); bookmark_del(node.id)}} icon="bookmark_remove" label="Remove bookmark"/>
|
<Button click={() => {dialog.close(); bookmark_del(node.id)}} icon="bookmark_remove" label="Remove bookmark"/>
|
||||||
{:else}
|
{:else}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher, onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import ListView from "./ListView.svelte"
|
import ListView from "./ListView.svelte"
|
||||||
import GalleryView from "./GalleryView.svelte"
|
import GalleryView from "./GalleryView.svelte"
|
||||||
import CompactView from "./CompactView.svelte"
|
import CompactView from "./CompactView.svelte"
|
||||||
@@ -11,13 +11,16 @@ import { FileAction, type FileActionHandler } from "./FileManagerLib";
|
|||||||
|
|
||||||
let nav = $state(new FSNavigator(false))
|
let nav = $state(new FSNavigator(false))
|
||||||
let modal: Modal = $state()
|
let modal: Modal = $state()
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
let directory_view = $state("")
|
let directory_view = $state("")
|
||||||
let large_icons = $state(false)
|
let large_icons = $state(false)
|
||||||
let show_hidden = $state(false)
|
let show_hidden = $state(false)
|
||||||
|
|
||||||
let { select_multiple = false }: {
|
let {
|
||||||
select_multiple?: boolean;
|
callback,
|
||||||
|
select_multiple = false
|
||||||
|
}: {
|
||||||
|
callback: (files: FSNode[]) => void
|
||||||
|
select_multiple?: boolean
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
export const open = (path: string) => {
|
export const open = (path: string) => {
|
||||||
@@ -113,7 +116,7 @@ let done = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selected_files.length > 0) {
|
if (selected_files.length > 0) {
|
||||||
dispatch("files", selected_files)
|
callback(selected_files)
|
||||||
}
|
}
|
||||||
modal.hide()
|
modal.hide()
|
||||||
}
|
}
|
||||||
|
@@ -172,7 +172,7 @@ const leave_confirmation = (e: BeforeUnloadEvent) => {
|
|||||||
<div class="body">
|
<div class="body">
|
||||||
{#each upload_queue as job}
|
{#each upload_queue as job}
|
||||||
{#if job.status !== "finished"}
|
{#if job.status !== "finished"}
|
||||||
<UploadProgress bind:this={job.component} job={job} on:finished={finish_upload}/>
|
<UploadProgress bind:this={job.component} job={job} finish={finish_upload}/>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,20 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import { upload_file } from "./UploadFunc";
|
import { upload_file } from "./UploadFunc";
|
||||||
import ProgressBar from "util/ProgressBar.svelte";
|
import ProgressBar from "util/ProgressBar.svelte";
|
||||||
import Button from "layout/Button.svelte"
|
import Button from "layout/Button.svelte"
|
||||||
import type { UploadJob } from "./FSUploadWidget.svelte";
|
import type { UploadJob } from "./FSUploadWidget.svelte";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
job = $bindable(),
|
job = $bindable(),
|
||||||
total = $bindable(0),
|
total = $bindable(0),
|
||||||
loaded = $bindable(0)
|
loaded = $bindable(0),
|
||||||
|
finish,
|
||||||
}: {
|
}: {
|
||||||
job: UploadJob;
|
job: UploadJob
|
||||||
total?: number;
|
total?: number
|
||||||
loaded?: number;
|
loaded?: number
|
||||||
|
finish: () => void
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let error_code = $state("")
|
let error_code = $state("")
|
||||||
@@ -31,7 +30,7 @@ export const start = () => {
|
|||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
job.status = "finished"
|
job.status = "finished"
|
||||||
dispatch("finished")
|
finish()
|
||||||
},
|
},
|
||||||
(code, message) => {
|
(code, message) => {
|
||||||
if (job.status === "finished") {
|
if (job.status === "finished") {
|
||||||
@@ -59,7 +58,7 @@ const cancel = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xhr = null
|
xhr = null
|
||||||
dispatch("finished")
|
finish()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -1,39 +1,40 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import IconBlock from "layout/IconBlock.svelte";
|
import IconBlock from "layout/IconBlock.svelte";
|
||||||
import { fs_thumbnail_url } from "lib/FilesystemAPI.svelte";
|
import { fs_thumbnail_url, FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import TextBlock from "layout/TextBlock.svelte"
|
import TextBlock from "layout/TextBlock.svelte"
|
||||||
import { formatDataVolume, formatDate } from "util/Formatting";
|
import { formatDataVolume, formatDate } from "util/Formatting";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let {
|
||||||
|
node,
|
||||||
let { nav, children }: {
|
open_details,
|
||||||
nav: FSNavigator;
|
children,
|
||||||
children?: import('svelte').Snippet;
|
}: {
|
||||||
|
node: FSNode
|
||||||
|
open_details: () => void
|
||||||
|
children?: import('svelte').Snippet
|
||||||
} = $props();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|
||||||
<h1>{$nav.base.name}</h1>
|
<h1>{node.name}</h1>
|
||||||
|
|
||||||
<IconBlock icon_href={fs_thumbnail_url($nav.base.path, 256, 256)}>
|
<IconBlock icon_href={fs_thumbnail_url(node.path, 256, 256)}>
|
||||||
Type: {$nav.base.file_type}<br/>
|
Type: {node.file_type}<br/>
|
||||||
Size: {formatDataVolume($nav.base.file_size, 3)}<br/>
|
Size: {formatDataVolume(node.file_size, 3)}<br/>
|
||||||
Upload date: {formatDate($nav.base.created, true, true, false)}
|
Upload date: {formatDate(node.created, true, true, false)}
|
||||||
<hr/>
|
<hr/>
|
||||||
<button class="button_highlight" onclick={() => {dispatch("download")}}>
|
<button class="button_highlight" onclick={() => node.download()}>
|
||||||
<i class="icon">download</i>
|
<i class="icon">download</i>
|
||||||
<span>Download</span>
|
<span>Download</span>
|
||||||
</button>
|
</button>
|
||||||
<button onclick={() => {dispatch("details")}}>
|
<button onclick={() => open_details()}>
|
||||||
<i class="icon">help</i>
|
<i class="icon">help</i>
|
||||||
<span>Details</span>
|
<span>Details</span>
|
||||||
</button>
|
</button>
|
||||||
</IconBlock>
|
</IconBlock>
|
||||||
|
|
||||||
{#if $nav.base.name === ".search_index.gz"}
|
{#if node.name === ".search_index.gz"}
|
||||||
<TextBlock>
|
<TextBlock>
|
||||||
<p>
|
<p>
|
||||||
Congratulations! You have found the search index. One of the
|
Congratulations! You have found the search index. One of the
|
||||||
|
@@ -15,11 +15,18 @@ import CustomBanner from "./CustomBanner.svelte";
|
|||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||||
import FsUploadWidget from "filesystem/upload_widget/FSUploadWidget.svelte";
|
import FsUploadWidget from "filesystem/upload_widget/FSUploadWidget.svelte";
|
||||||
import EditWindow from "filesystem/edit_window/EditWindow.svelte";
|
import EditWindow from "filesystem/edit_window/EditWindow.svelte";
|
||||||
|
import DetailsWindow from "filesystem/DetailsWindow.svelte";
|
||||||
|
|
||||||
let { nav, upload_widget, edit_window }: {
|
let {
|
||||||
nav: FSNavigator;
|
nav,
|
||||||
upload_widget: FsUploadWidget;
|
upload_widget,
|
||||||
edit_window: EditWindow;
|
edit_window,
|
||||||
|
details_window,
|
||||||
|
}: {
|
||||||
|
nav: FSNavigator
|
||||||
|
upload_widget: FsUploadWidget
|
||||||
|
edit_window: EditWindow
|
||||||
|
details_window: DetailsWindow
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let viewer: any = $state()
|
let viewer: any = $state()
|
||||||
@@ -89,23 +96,23 @@ export const seek = (delta: number) => {
|
|||||||
{:else if viewer_type === "image"}
|
{:else if viewer_type === "image"}
|
||||||
<Image nav={nav} bind:this={viewer}/>
|
<Image nav={nav} bind:this={viewer}/>
|
||||||
{:else if viewer_type === "video"}
|
{:else if viewer_type === "video"}
|
||||||
<Video nav={nav} bind:this={viewer} on:open_sibling/>
|
<Video node={$nav.base} bind:this={viewer} open_sibling={(d) => nav.open_sibling(d)}/>
|
||||||
{:else if viewer_type === "pdf"}
|
{:else if viewer_type === "pdf"}
|
||||||
<Pdf nav={nav} bind:this={viewer}/>
|
<Pdf node={$nav.base} bind:this={viewer}/>
|
||||||
{:else if viewer_type === "text"}
|
{:else if viewer_type === "text"}
|
||||||
<Text nav={nav} bind:this={viewer}>
|
<Text node={$nav.base} bind:this={viewer}>
|
||||||
<CustomBanner path={$nav.path}/>
|
<CustomBanner path={$nav.path}/>
|
||||||
</Text>
|
</Text>
|
||||||
{:else if viewer_type === "torrent"}
|
{:else if viewer_type === "torrent"}
|
||||||
<Torrent nav={nav} bind:this={viewer} on:download>
|
<Torrent node={$nav.base} bind:this={viewer}>
|
||||||
<CustomBanner path={$nav.path}/>
|
<CustomBanner path={$nav.path}/>
|
||||||
</Torrent>
|
</Torrent>
|
||||||
{:else if viewer_type === "zip"}
|
{:else if viewer_type === "zip"}
|
||||||
<Zip nav={nav} bind:this={viewer} on:download>
|
<Zip node={$nav.base} bind:this={viewer}>
|
||||||
<CustomBanner path={$nav.path}/>
|
<CustomBanner path={$nav.path}/>
|
||||||
</Zip>
|
</Zip>
|
||||||
{:else}
|
{:else}
|
||||||
<File nav={nav} on:download on:details>
|
<File node={$nav.base} open_details={() => details_window.toggle()}>
|
||||||
<CustomBanner path={$nav.path}/>
|
<CustomBanner path={$nav.path}/>
|
||||||
</File>
|
</File>
|
||||||
{/if}
|
{/if}
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import { swipe_nav } from "lib/SwipeNavigate";
|
import { swipe_nav } from "lib/SwipeNavigate";
|
||||||
import { fs_path_url } from "lib/FilesystemAPI.svelte";
|
import { fs_path_url } from "lib/FilesystemAPI.svelte";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||||
|
import { loading_finish, loading_start } from "lib/Loading";
|
||||||
let dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
let { nav }: {
|
let { nav }: {
|
||||||
nav: FSNavigator;
|
nav: FSNavigator;
|
||||||
@@ -18,7 +16,7 @@ let swipe_prev = $state(true)
|
|||||||
let swipe_next = $state(true)
|
let swipe_next = $state(true)
|
||||||
|
|
||||||
export const update = async () => {
|
export const update = async () => {
|
||||||
dispatch("loading", true)
|
loading_start()
|
||||||
|
|
||||||
// Figure out if there are previous or next files. If not then we disable
|
// Figure out if there are previous or next files. If not then we disable
|
||||||
// swiping controls in that direction
|
// swiping controls in that direction
|
||||||
@@ -32,7 +30,7 @@ export const update = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const on_load = () => dispatch("loading", false)
|
const on_load = () => loading_finish()
|
||||||
|
|
||||||
const mousedown = (e: MouseEvent) => {
|
const mousedown = (e: MouseEvent) => {
|
||||||
if (!dragging && e.which === 1 && zoom) {
|
if (!dragging && e.which === 1 && zoom) {
|
||||||
|
@@ -1,15 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fs_path_url } from "lib/FilesystemAPI.svelte";
|
import { fs_path_url, FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
|
||||||
|
|
||||||
let { nav }: {
|
let { node }: { node: FSNode } = $props();
|
||||||
nav: FSNavigator;
|
|
||||||
} = $props();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<iframe
|
<iframe
|
||||||
class="container"
|
class="container"
|
||||||
src={"/res/misc/pdf-viewer/web/viewer.html?file="+fs_path_url($nav.base.path)}
|
src={"/res/misc/pdf-viewer/web/viewer.html?file="+fs_path_url(node.path)}
|
||||||
title="PDF viewer">
|
title="PDF viewer">
|
||||||
</iframe>
|
</iframe>
|
||||||
|
|
||||||
|
@@ -1,31 +1,33 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { tick } from "svelte";
|
import { tick } from "svelte";
|
||||||
import { fs_path_url, type FSNode } from "lib/FilesystemAPI.svelte";
|
import { fs_path_url, type FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
|
||||||
|
|
||||||
let { nav, children }: {
|
let {
|
||||||
nav: FSNavigator;
|
node,
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
node: FSNode
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let text_type = $state("text")
|
let text_type = $state("text")
|
||||||
|
|
||||||
export const update = () => {
|
export const update = () => {
|
||||||
console.debug("Loading text file", nav.base.name)
|
console.debug("Loading text file", node.name)
|
||||||
|
|
||||||
if (nav.base.file_size > 1 << 21) { // File larger than 2 MiB
|
if (node.file_size > 1 << 21) { // File larger than 2 MiB
|
||||||
text_pre.innerText = "File is too large to view online.\nPlease download and view it locally."
|
text_pre.innerText = "File is too large to view online.\nPlease download and view it locally."
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
nav.base.file_type.startsWith("text/markdown") ||
|
node.file_type.startsWith("text/markdown") ||
|
||||||
nav.base.name.endsWith(".md") ||
|
node.name.endsWith(".md") ||
|
||||||
nav.base.name.endsWith(".markdown")
|
node.name.endsWith(".markdown")
|
||||||
) {
|
) {
|
||||||
markdown(nav.base)
|
markdown(node)
|
||||||
} else {
|
} else {
|
||||||
text(nav.base)
|
text(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,21 +13,20 @@ export type TorrentFile = {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import Magnet from "icons/Magnet.svelte";
|
import Magnet from "icons/Magnet.svelte";
|
||||||
import { formatDate } from "util/Formatting"
|
import { formatDate } from "util/Formatting"
|
||||||
import TorrentItem from "./TorrentItem.svelte"
|
import TorrentItem from "./TorrentItem.svelte"
|
||||||
import IconBlock from "layout/IconBlock.svelte";
|
import IconBlock from "layout/IconBlock.svelte";
|
||||||
import TextBlock from "layout/TextBlock.svelte"
|
import TextBlock from "layout/TextBlock.svelte"
|
||||||
import { fs_node_icon, fs_path_url } from "lib/FilesystemAPI.svelte";
|
import { fs_node_icon, fs_path_url, FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import CopyButton from "layout/CopyButton.svelte";
|
import CopyButton from "layout/CopyButton.svelte";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
|
||||||
import { loading_finish, loading_start } from "lib/Loading";
|
import { loading_finish, loading_start } from "lib/Loading";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let {
|
||||||
|
node,
|
||||||
let { nav, children }: {
|
children
|
||||||
nav: FSNavigator;
|
}: {
|
||||||
|
node: FSNode;
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ let status = $state("loading")
|
|||||||
export const update = async () => {
|
export const update = async () => {
|
||||||
try {
|
try {
|
||||||
loading_start()
|
loading_start()
|
||||||
let resp = await fetch(fs_path_url(nav.base.path)+"?torrent_info")
|
let resp = await fetch(fs_path_url(node.path)+"?torrent_info")
|
||||||
|
|
||||||
if (resp.status >= 400) {
|
if (resp.status >= 400) {
|
||||||
let json = await resp.json()
|
let json = await resp.json()
|
||||||
@@ -73,9 +72,9 @@ let magnet = $state("")
|
|||||||
|
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|
||||||
<h1>{$nav.base.name}</h1>
|
<h1>{node.name}</h1>
|
||||||
|
|
||||||
<IconBlock icon_href={fs_node_icon($nav.base, 256, 256)}>
|
<IconBlock icon_href={fs_node_icon(node, 256, 256)}>
|
||||||
{#if status === "finished"}
|
{#if status === "finished"}
|
||||||
Created by: {torrent.created_by}<br/>
|
Created by: {torrent.created_by}<br/>
|
||||||
Comment: {torrent.comment}<br/>
|
Comment: {torrent.comment}<br/>
|
||||||
@@ -96,7 +95,7 @@ let magnet = $state("")
|
|||||||
Torrent file could not be parsed. It may be corrupted.
|
Torrent file could not be parsed. It may be corrupted.
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
<button onclick={() => {dispatch("download")}} class="button">
|
<button onclick={() => node.download()} class="button">
|
||||||
<i class="icon">download</i>
|
<i class="icon">download</i>
|
||||||
<span>Download torrent file</span>
|
<span>Download torrent file</span>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, createEventDispatcher, tick } from "svelte";
|
import { onMount, tick } from "svelte";
|
||||||
import { video_position } from "lib/VideoPosition";
|
import { video_position } from "lib/VideoPosition";
|
||||||
import { fs_path_url } from "lib/FilesystemAPI.svelte";
|
import { fs_path_url, FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
let { nav }: {
|
let {
|
||||||
nav: FSNavigator;
|
node,
|
||||||
|
open_sibling,
|
||||||
|
}: {
|
||||||
|
node: FSNode
|
||||||
|
open_sibling: (delta: number) => void
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
// Used to detect when the file path changes
|
// Used to detect when the file path changes
|
||||||
@@ -21,20 +23,20 @@ let loop = $state(false)
|
|||||||
export const update = async () => {
|
export const update = async () => {
|
||||||
if (media_session) {
|
if (media_session) {
|
||||||
navigator.mediaSession.metadata = new MediaMetadata({
|
navigator.mediaSession.metadata = new MediaMetadata({
|
||||||
title: nav.base.name,
|
title: node.name,
|
||||||
artist: "pixeldrain",
|
artist: "pixeldrain",
|
||||||
album: "unknown",
|
album: "unknown",
|
||||||
});
|
});
|
||||||
console.debug("Updating media session")
|
console.debug("Updating media session")
|
||||||
}
|
}
|
||||||
|
|
||||||
loop = nav.base.name.includes(".loop.")
|
loop = node.name.includes(".loop.")
|
||||||
|
|
||||||
// When the component receives a new ID the video track does not
|
// When the component receives a new ID the video track does not
|
||||||
// automatically start playing the new video. So we use this little hack to
|
// automatically start playing the new video. So we use this little hack to
|
||||||
// make sure that the video is unloaded and loaded when the ID changes
|
// make sure that the video is unloaded and loaded when the ID changes
|
||||||
if (nav.base.path != last_path) {
|
if (node.path != last_path) {
|
||||||
last_path = nav.base.path
|
last_path = node.path
|
||||||
loaded = false
|
loaded = false
|
||||||
await tick()
|
await tick()
|
||||||
loaded = true
|
loaded = true
|
||||||
@@ -51,8 +53,7 @@ export const toggle_fullscreen = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const seek = (delta: number) => {
|
||||||
export const seek = delta => {
|
|
||||||
// fastseek can be pretty imprecise, so we don't use it for small seeks
|
// fastseek can be pretty imprecise, so we don't use it for small seeks
|
||||||
// below 5 seconds
|
// below 5 seconds
|
||||||
if (player.fastSeek && delta > 5) {
|
if (player.fastSeek && delta > 5) {
|
||||||
@@ -68,8 +69,8 @@ onMount(() => {
|
|||||||
navigator.mediaSession.setActionHandler('play', () => player.play());
|
navigator.mediaSession.setActionHandler('play', () => player.play());
|
||||||
navigator.mediaSession.setActionHandler('pause', () => player.pause());
|
navigator.mediaSession.setActionHandler('pause', () => player.pause());
|
||||||
navigator.mediaSession.setActionHandler('stop', () => player.pause());
|
navigator.mediaSession.setActionHandler('stop', () => player.pause());
|
||||||
navigator.mediaSession.setActionHandler('previoustrack', () => dispatch("open_sibling", -1));
|
navigator.mediaSession.setActionHandler('previoustrack', () => open_sibling(-1));
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', () => dispatch("open_sibling", 1));
|
navigator.mediaSession.setActionHandler('nexttrack', () => open_sibling(1));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -85,9 +86,9 @@ const video_keydown = (e: KeyboardEvent) => {
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{#if
|
{#if
|
||||||
$nav.base.file_type === "video/x-matroska" ||
|
node.file_type === "video/x-matroska" ||
|
||||||
$nav.base.file_type === "video/quicktime" ||
|
node.file_type === "video/quicktime" ||
|
||||||
$nav.base.file_type === "video/x-ms-asf"}
|
node.file_type === "video/x-ms-asf"}
|
||||||
<div class="compatibility_warning">
|
<div class="compatibility_warning">
|
||||||
This video file type is not compatible with every web
|
This video file type is not compatible with every web
|
||||||
browser. If the video fails to play you can try downloading
|
browser. If the video fails to play you can try downloading
|
||||||
@@ -108,16 +109,16 @@ const video_keydown = (e: KeyboardEvent) => {
|
|||||||
onpause={() => playing = false}
|
onpause={() => playing = false}
|
||||||
onplay={() => playing = true}
|
onplay={() => playing = true}
|
||||||
onkeydown={video_keydown}
|
onkeydown={video_keydown}
|
||||||
use:video_position={() => $nav.base.sha256_sum.substring(0, 8)}
|
use:video_position={() => node.sha256_sum.substring(0, 8)}
|
||||||
>
|
>
|
||||||
<source src={fs_path_url($nav.base.path)} type={$nav.base.file_type} />
|
<source src={fs_path_url(node.path)} type={node.file_type} />
|
||||||
</video>
|
</video>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<div class="spacer"></div>
|
<div class="spacer"></div>
|
||||||
<button onclick={() => dispatch("open_sibling", -1)}>
|
<button onclick={() => open_sibling(-1)}>
|
||||||
<i class="icon">skip_previous</i>
|
<i class="icon">skip_previous</i>
|
||||||
</button>
|
</button>
|
||||||
<button onclick={() => seek(-10)}>
|
<button onclick={() => seek(-10)}>
|
||||||
@@ -133,7 +134,7 @@ const video_keydown = (e: KeyboardEvent) => {
|
|||||||
<button onclick={() => seek(10)}>
|
<button onclick={() => seek(10)}>
|
||||||
<i class="icon">forward_10</i>
|
<i class="icon">forward_10</i>
|
||||||
</button>
|
</button>
|
||||||
<button onclick={() => dispatch("open_sibling", 1)}>
|
<button onclick={() => open_sibling(1)}>
|
||||||
<i class="icon">skip_next</i>
|
<i class="icon">skip_next</i>
|
||||||
</button>
|
</button>
|
||||||
<div style="width: 16px; height: 8px;"></div>
|
<div style="width: 16px; height: 8px;"></div>
|
||||||
|
@@ -8,19 +8,18 @@ export type ZipEntry = {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import { formatDataVolume, formatDate } from "util/Formatting"
|
import { formatDataVolume, formatDate } from "util/Formatting"
|
||||||
import ZipItem from "filesystem/viewers/ZipItem.svelte";
|
import ZipItem from "filesystem/viewers/ZipItem.svelte";
|
||||||
import IconBlock from "layout/IconBlock.svelte";
|
import IconBlock from "layout/IconBlock.svelte";
|
||||||
import TextBlock from "layout/TextBlock.svelte"
|
import TextBlock from "layout/TextBlock.svelte"
|
||||||
import { fs_node_icon, fs_path_url } from "lib/FilesystemAPI.svelte";
|
import { fs_node_icon, fs_path_url, FSNode } from "lib/FilesystemAPI.svelte";
|
||||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
|
||||||
import { loading_finish, loading_start } from "lib/Loading";
|
import { loading_finish, loading_start } from "lib/Loading";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let {
|
||||||
|
node,
|
||||||
let { nav, children }: {
|
children,
|
||||||
nav: FSNavigator;
|
}: {
|
||||||
|
node: FSNode;
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@ let archive_type = $state("")
|
|||||||
let truncated = $state(false)
|
let truncated = $state(false)
|
||||||
|
|
||||||
export const update = async () => {
|
export const update = async () => {
|
||||||
if (nav.base.file_type === "application/x-7z-compressed") {
|
if (node.file_type === "application/x-7z-compressed") {
|
||||||
archive_type = "7z"
|
archive_type = "7z"
|
||||||
} else {
|
} else {
|
||||||
archive_type = ""
|
archive_type = ""
|
||||||
@@ -42,7 +41,7 @@ export const update = async () => {
|
|||||||
try {
|
try {
|
||||||
loading_start()
|
loading_start()
|
||||||
status = "loading"
|
status = "loading"
|
||||||
let resp = await fetch(fs_path_url(nav.base.path)+"?zip_info")
|
let resp = await fetch(fs_path_url(node.path)+"?zip_info")
|
||||||
|
|
||||||
if (resp.status >= 400) {
|
if (resp.status >= 400) {
|
||||||
status = "parse_failed"
|
status = "parse_failed"
|
||||||
@@ -56,13 +55,13 @@ export const update = async () => {
|
|||||||
if (zip.properties !== undefined) {
|
if (zip.properties !== undefined) {
|
||||||
if (zip.properties.includes("read_individual_files")) {
|
if (zip.properties.includes("read_individual_files")) {
|
||||||
// Set the download URL for each file in the zip
|
// Set the download URL for each file in the zip
|
||||||
recursive_set_url(fs_path_url(nav.base.path)+"?zip_file=", zip)
|
recursive_set_url(fs_path_url(node.path)+"?zip_file=", zip)
|
||||||
}
|
}
|
||||||
truncated = zip.properties.includes("truncated")
|
truncated = zip.properties.includes("truncated")
|
||||||
}
|
}
|
||||||
|
|
||||||
uncomp_size = recursive_size(zip)
|
uncomp_size = recursive_size(zip)
|
||||||
comp_ratio = (uncomp_size / nav.base.file_size)
|
comp_ratio = (uncomp_size / node.file_size)
|
||||||
status = "finished"
|
status = "finished"
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
@@ -98,22 +97,22 @@ const recursive_size = (file: ZipEntry) => {
|
|||||||
|
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|
||||||
<h1>{$nav.base.name}</h1>
|
<h1>{node.name}</h1>
|
||||||
|
|
||||||
<IconBlock icon_href={fs_node_icon($nav.base, 256, 256)}>
|
<IconBlock icon_href={fs_node_icon(node, 256, 256)}>
|
||||||
{#if archive_type === "7z"}
|
{#if archive_type === "7z"}
|
||||||
This is a 7-zip archive. You will need
|
This is a 7-zip archive. You will need
|
||||||
<a href="https://www.7-zip.org/">7-zip</a> or compatible software to
|
<a href="https://www.7-zip.org/">7-zip</a> or compatible software to
|
||||||
extract it<br/>
|
extract it<br/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
Compressed size: {formatDataVolume($nav.base.file_size, 3)}<br/>
|
Compressed size: {formatDataVolume(node.file_size, 3)}<br/>
|
||||||
{#if !truncated}
|
{#if !truncated}
|
||||||
Uncompressed size: {formatDataVolume(zip.size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
Uncompressed size: {formatDataVolume(zip.size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
||||||
{/if}
|
{/if}
|
||||||
Uploaded on: {formatDate($nav.base.created, true, true, true)}
|
Uploaded on: {formatDate(node.created, true, true, true)}
|
||||||
<br/>
|
<br/>
|
||||||
<button class="button_highlight" onclick={() => {dispatch("download")}}>
|
<button class="button_highlight" onclick={() => node.download()}>
|
||||||
<i class="icon">download</i>
|
<i class="icon">download</i>
|
||||||
<span>Download</span>
|
<span>Download</span>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -1,83 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import { formatDataVolume, formatDuration } from "util/Formatting";
|
|
||||||
import { stats } from "lib/StatsSocket"
|
|
||||||
import TextBlock from "./TextBlock.svelte"
|
|
||||||
import IconBlock from "./IconBlock.svelte";
|
|
||||||
import { user } from "lib/UserStore";
|
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
let {
|
|
||||||
file_size = 0,
|
|
||||||
file_name = "",
|
|
||||||
file_type = "",
|
|
||||||
icon_href = ""
|
|
||||||
}: {
|
|
||||||
file_size?: number;
|
|
||||||
file_name?: string;
|
|
||||||
file_type?: string;
|
|
||||||
icon_href?: string;
|
|
||||||
} = $props();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<TextBlock>
|
|
||||||
<img src="/res/img/slow_down.webp" class="header_image" alt="Yea, I'm gonna need you to slow down a bit"/>
|
|
||||||
<p>
|
|
||||||
Pixeldrain's free tier is supported by my Patrons. There's only so much
|
|
||||||
that you can do with the budget they provide.
|
|
||||||
{formatDataVolume($stats.limits.transfer_limit, 3)} per day is about the
|
|
||||||
most I can give away for free while keeping it fair for everyone, and
|
|
||||||
according to our records you have already downloaded
|
|
||||||
{formatDataVolume($stats.limits.transfer_limit_used, 3)}.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
It's not that I want to withold this file from you, it's just that I
|
|
||||||
don't want pixeldrain to fall into bankruptcy like so many of the
|
|
||||||
websites that came before me. So if you really want this file you have a
|
|
||||||
few options:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Come back tomorrow when your free transfer limit resets
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Download the file at a limited rate of {formatDataVolume($stats.limits.speed_limit, 3)}/s. This will take at
|
|
||||||
least {formatDuration((file_size/($stats.limits.speed_limit))*1000, 0)}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="/user/prepaid/deposit" target="_blank" class="button button_highlight">
|
|
||||||
<i class="icon">bolt</i> Get Premium
|
|
||||||
</a>
|
|
||||||
and earn my eternal gratitude
|
|
||||||
{#if $user.username === undefined || $user.username === ""}
|
|
||||||
(you will need a <a href="/register">pixeldrain account</a> to
|
|
||||||
receive the benefits)
|
|
||||||
{/if}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<IconBlock icon_href={icon_href}>
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr><td colspan="2">{file_name}</td></tr>
|
|
||||||
<tr><td>Type</td><td>{file_type}</td></tr>
|
|
||||||
<tr><td>Size</td><td>{formatDataVolume(file_size, 3)}</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<button onclick={() => {dispatch("download")}}>
|
|
||||||
<i class="icon">download</i> Download
|
|
||||||
</button>
|
|
||||||
</IconBlock>
|
|
||||||
|
|
||||||
<TextBlock>
|
|
||||||
Also, I believe you have my stapler. Please give it back.
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.header_image {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -58,6 +58,22 @@ export class FSNode {
|
|||||||
(this.user_permissions !== undefined && Object.keys(this.user_permissions).length > 0) ||
|
(this.user_permissions !== undefined && Object.keys(this.user_permissions).length > 0) ||
|
||||||
(this.password_permissions !== undefined && Object.keys(this.password_permissions).length > 0)
|
(this.password_permissions !== undefined && Object.keys(this.password_permissions).length > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
download = () => {
|
||||||
|
const a = document.createElement("a")
|
||||||
|
|
||||||
|
if (this.type === "file") {
|
||||||
|
a.href = fs_path_url(this.path) + "?attach"
|
||||||
|
a.download = this.name
|
||||||
|
} else if (this.type === "dir") {
|
||||||
|
a.href = fs_path_url(this.path) + "?bulk_download"
|
||||||
|
a.download = this.name + ".zip"
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can't call .click() on an element that is not in the DOM. But
|
||||||
|
// emitting a click event works
|
||||||
|
a.dispatchEvent(new MouseEvent("click"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FSNodeProperties = {
|
export type FSNodeProperties = {
|
||||||
@@ -400,19 +416,3 @@ export const fs_share_path = (path: FSNode[]): string => {
|
|||||||
|
|
||||||
return share_url
|
return share_url
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_download = (node: FSNode) => {
|
|
||||||
const a = document.createElement("a")
|
|
||||||
|
|
||||||
if (node.type === "file") {
|
|
||||||
a.href = fs_path_url(node.path) + "?attach"
|
|
||||||
a.download = node.name
|
|
||||||
} else if (node.type === "dir") {
|
|
||||||
a.href = fs_path_url(node.path) + "?bulk_download"
|
|
||||||
a.download = node.name + ".zip"
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can't call .click() on an element that is not in the DOM. But
|
|
||||||
// emitting a click event works
|
|
||||||
a.dispatchEvent(new MouseEvent("click"))
|
|
||||||
}
|
|
||||||
|
@@ -6,9 +6,8 @@ let global_index = 10000;
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createBubbler, stopPropagation } from 'svelte/legacy';
|
import { createBubbler, stopPropagation } from 'svelte/legacy';
|
||||||
|
|
||||||
const bubble = createBubbler();
|
const bubble = createBubbler();
|
||||||
import { createEventDispatcher, type Snippet } from "svelte";
|
import { type Snippet } from "svelte";
|
||||||
import { fade } from "svelte/transition";
|
import { fade } from "svelte/transition";
|
||||||
import Button from "layout/Button.svelte";
|
import Button from "layout/Button.svelte";
|
||||||
|
|
||||||
@@ -42,16 +41,11 @@ const load_bg = background => {
|
|||||||
global_index++;
|
global_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
export const show = () => { set_visible(true) }
|
export const show = () => { set_visible(true) }
|
||||||
export const hide = () => { set_visible(false) }
|
export const hide = () => { set_visible(false) }
|
||||||
export const toggle = () => { set_visible(!visible) }
|
export const toggle = () => { set_visible(!visible) }
|
||||||
export const is_visible = () => { return visible }
|
export const is_visible = () => { return visible }
|
||||||
export const set_visible = vis => {
|
export const set_visible = (vis: boolean) => visible = vis
|
||||||
visible = vis
|
|
||||||
dispatch("is_visible", visible)
|
|
||||||
}
|
|
||||||
|
|
||||||
const keydown = (e: KeyboardEvent) => {
|
const keydown = (e: KeyboardEvent) => {
|
||||||
if ((document.activeElement as any).type && (document.activeElement as any).type === "text") {
|
if ((document.activeElement as any).type && (document.activeElement as any).type === "text") {
|
||||||
|
@@ -1,64 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
let dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
let { theme = $bindable("") }: {
|
|
||||||
theme?: string;
|
|
||||||
} = $props();
|
|
||||||
|
|
||||||
let set = (s: string) => {
|
|
||||||
theme = s
|
|
||||||
dispatch("theme_change", theme)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="center">
|
|
||||||
<button class:button_highlight={theme===""} onclick={() => {set("")}}>
|
|
||||||
None
|
|
||||||
</button>
|
|
||||||
<button class="group_first" class:button_highlight={theme==="nord"} onclick={() => {set("nord")}}>
|
|
||||||
Nord
|
|
||||||
</button>
|
|
||||||
<button class="group_middle" class:button_highlight={theme==="nord_dark"} onclick={() => {set("nord_dark")}}>
|
|
||||||
dark
|
|
||||||
</button>
|
|
||||||
<button class="group_last" class:button_highlight={theme==="nord_light"} onclick={() => {set("nord_light")}}>
|
|
||||||
light
|
|
||||||
</button>
|
|
||||||
<button class="group_first" class:button_highlight={theme==="solarized"} onclick={() => {set("solarized")}}>
|
|
||||||
Solarized
|
|
||||||
</button>
|
|
||||||
<button class="group_middle" class:button_highlight={theme==="solarized_dark"} onclick={() => {set("solarized_dark")}}>
|
|
||||||
dark
|
|
||||||
</button>
|
|
||||||
<button class="group_last" class:button_highlight={theme==="solarized_light"} onclick={() => {set("solarized_light")}}>
|
|
||||||
light
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="purple_drain"} onclick={() => {set("purple_drain")}}>
|
|
||||||
Purple drain
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="classic"} onclick={() => {set("classic")}}>
|
|
||||||
Classic
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="maroon"} onclick={() => {set("maroon")}}>
|
|
||||||
Maroon
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="hacker"} onclick={() => {set("hacker")}}>
|
|
||||||
Hacker
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="canta"} onclick={() => {set("canta")}}>
|
|
||||||
Canta
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="skeuos"} onclick={() => {set("skeuos")}}>
|
|
||||||
Skeuos
|
|
||||||
</button>
|
|
||||||
<button class:button_highlight={theme==="sweet"} onclick={() => {set("sweet")}}>
|
|
||||||
Sweet
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -9,6 +9,6 @@
|
|||||||
"target": "ES2017",
|
"target": "ES2017",
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"module": "preserve",
|
"module": "preserve",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user