2020-11-11 00:00:54 +01:00
|
|
|
<script>
|
2023-05-30 15:51:10 +02:00
|
|
|
import { onMount } from 'svelte';
|
2022-04-26 15:23:57 +02:00
|
|
|
import LoadingIndicator from '../util/LoadingIndicator.svelte';
|
2024-02-16 14:50:34 +01:00
|
|
|
import EditWindow from './edit_window/EditWindow.svelte';
|
2023-05-17 15:34:56 +02:00
|
|
|
import Toolbar from './Toolbar.svelte';
|
|
|
|
import Breadcrumbs from './Breadcrumbs.svelte';
|
|
|
|
import DetailsWindow from './DetailsWindow.svelte';
|
|
|
|
import FilePreview from './viewers/FilePreview.svelte';
|
2024-09-10 18:51:13 +02:00
|
|
|
import FSUploadWidget from './upload_widget/FSUploadWidget.svelte';
|
2024-11-19 15:31:51 +01:00
|
|
|
import { fs_path_url } from './FilesystemAPI.mjs';
|
2024-03-12 17:53:53 +01:00
|
|
|
import Menu from './Menu.svelte';
|
2024-08-30 15:35:53 +02:00
|
|
|
import { FSNavigator } from "./FSNavigator"
|
2024-08-09 13:47:10 +02:00
|
|
|
import { writable } from 'svelte/store';
|
2024-09-05 17:28:31 +02:00
|
|
|
import TransferLimit from '../file_viewer/TransferLimit.svelte';
|
2024-09-12 15:11:50 +02:00
|
|
|
import { stats } from "../lib/StatsSocket.js"
|
2024-09-10 18:51:13 +02:00
|
|
|
import { css_from_path } from './edit_window/Branding';
|
2020-11-11 00:00:54 +01:00
|
|
|
|
2024-04-11 19:33:26 +02:00
|
|
|
let file_viewer
|
2024-04-11 20:32:55 +02:00
|
|
|
let file_preview
|
2023-11-16 12:17:36 +01:00
|
|
|
let toolbar
|
2023-05-29 18:01:23 +02:00
|
|
|
let upload_widget
|
2023-05-17 15:34:56 +02:00
|
|
|
let download_frame
|
2020-11-11 00:00:54 +01:00
|
|
|
let details_visible = false
|
2023-05-11 19:07:29 +02:00
|
|
|
let edit_window
|
2023-05-17 15:34:56 +02:00
|
|
|
let edit_visible = false
|
2020-11-11 00:00:54 +01:00
|
|
|
|
2024-08-09 13:47:10 +02:00
|
|
|
const loading = writable(true)
|
2024-08-30 15:35:53 +02:00
|
|
|
const nav = new FSNavigator(true)
|
2023-05-17 15:34:56 +02:00
|
|
|
|
2024-08-09 13:02:07 +02:00
|
|
|
onMount(() => {
|
2024-08-09 13:47:10 +02:00
|
|
|
nav.loading = loading
|
2024-08-09 13:02:07 +02:00
|
|
|
nav.open_node(window.initial_node, false)
|
2020-11-11 00:00:54 +01:00
|
|
|
|
2024-08-09 13:02:07 +02:00
|
|
|
// Subscribe to navigation updates. This function returns a deconstructor
|
|
|
|
// which we can conveniently return from our mount function as well
|
|
|
|
return nav.subscribe(nav => {
|
|
|
|
if (!nav.initialized) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Custom CSS rules for the whole viewer
|
2024-09-10 18:51:13 +02:00
|
|
|
document.documentElement.style = css_from_path(nav.path)
|
2020-11-17 23:39:27 +01:00
|
|
|
|
2024-08-09 13:47:10 +02:00
|
|
|
loading.set(false)
|
2024-08-09 13:02:07 +02:00
|
|
|
})
|
|
|
|
})
|
2020-11-11 00:00:54 +01:00
|
|
|
|
|
|
|
const keydown = e => {
|
2020-12-01 23:01:21 +01:00
|
|
|
if (e.ctrlKey || e.altKey || e.metaKey) {
|
|
|
|
return // prevent custom shortcuts from interfering with system shortcuts
|
2024-02-16 11:49:38 +01:00
|
|
|
} else if (document.activeElement.type && document.activeElement.type === "text") {
|
2021-03-04 15:42:46 +01:00
|
|
|
return // Prevent shortcuts from interfering with input fields
|
|
|
|
}
|
2020-12-01 23:01:21 +01:00
|
|
|
|
2024-03-12 17:53:53 +01:00
|
|
|
let action_performed = true
|
2020-11-11 00:00:54 +01:00
|
|
|
switch (e.key) {
|
2023-11-16 12:17:36 +01:00
|
|
|
case "c":
|
|
|
|
toolbar.copy_link()
|
|
|
|
break;
|
2020-11-26 11:13:27 +01:00
|
|
|
case "i":
|
2023-05-17 15:34:56 +02:00
|
|
|
details_visible = !details_visible
|
|
|
|
break;
|
|
|
|
case "e":
|
|
|
|
if (edit_visible) {
|
|
|
|
edit_visible = false
|
|
|
|
} else {
|
2024-08-09 13:02:07 +02:00
|
|
|
edit_window.edit(nav.base, true, "file")
|
2023-05-17 15:34:56 +02:00
|
|
|
}
|
2020-12-01 23:01:21 +01:00
|
|
|
break;
|
2020-11-26 11:13:27 +01:00
|
|
|
case "s":
|
|
|
|
download()
|
2020-12-01 23:01:21 +01:00
|
|
|
break;
|
|
|
|
case "r":
|
2024-08-09 13:02:07 +02:00
|
|
|
nav.shuffle = !nav.shuffle
|
2020-12-01 23:01:21 +01:00
|
|
|
break;
|
2025-02-03 16:29:26 +01:00
|
|
|
case "f": // F fullscreen
|
|
|
|
if (toolbar) {
|
|
|
|
toolbar.toggle_fullscreen()
|
|
|
|
}
|
|
|
|
break
|
2023-05-17 15:34:56 +02:00
|
|
|
case "a":
|
|
|
|
case "ArrowLeft":
|
2024-08-09 13:02:07 +02:00
|
|
|
nav.open_sibling(-1)
|
2020-12-01 23:01:21 +01:00
|
|
|
break;
|
2023-05-17 15:34:56 +02:00
|
|
|
case "d":
|
|
|
|
case "ArrowRight":
|
2024-08-09 13:02:07 +02:00
|
|
|
nav.open_sibling(1)
|
2020-12-01 23:01:21 +01:00
|
|
|
break;
|
2024-04-11 20:32:55 +02:00
|
|
|
case " ": // Spacebar pauses / unpauses video and audio playback
|
|
|
|
if (file_preview) {
|
2025-01-27 21:05:18 +01:00
|
|
|
if (file_preview.toggle_playback()) {
|
2025-02-03 16:29:26 +01:00
|
|
|
e.preventDefault()
|
|
|
|
e.stopPropagation()
|
2025-01-27 21:05:18 +01:00
|
|
|
}
|
2024-04-11 20:32:55 +02:00
|
|
|
}
|
|
|
|
break
|
2025-02-03 15:38:07 +01:00
|
|
|
case "m": // M mutes / unmutes audio
|
|
|
|
if (file_preview) {
|
|
|
|
file_preview.toggle_mute()
|
|
|
|
}
|
|
|
|
break
|
2024-08-14 19:58:25 +02:00
|
|
|
case "h":
|
|
|
|
file_preview.seek(-20)
|
|
|
|
break
|
|
|
|
case "j":
|
|
|
|
file_preview.seek(-5)
|
|
|
|
break
|
|
|
|
case "k":
|
|
|
|
file_preview.seek(5)
|
|
|
|
break
|
|
|
|
case "l":
|
|
|
|
file_preview.seek(20)
|
|
|
|
break
|
|
|
|
case ",":
|
|
|
|
file_preview.seek(-0.04) // Roughly a single frame.. assuming 25fps
|
|
|
|
break
|
|
|
|
case ".":
|
|
|
|
file_preview.seek(0.04)
|
|
|
|
break
|
2024-03-12 17:53:53 +01:00
|
|
|
default:
|
|
|
|
action_performed = false
|
2020-11-11 00:00:54 +01:00
|
|
|
}
|
2023-05-25 17:06:17 +02:00
|
|
|
|
2024-03-12 17:53:53 +01:00
|
|
|
if (action_performed) {
|
|
|
|
e.preventDefault()
|
|
|
|
}
|
2020-11-11 00:00:54 +01:00
|
|
|
};
|
|
|
|
|
2020-11-17 23:39:27 +01:00
|
|
|
const download = () => {
|
2024-08-09 13:02:07 +02:00
|
|
|
if (nav.base.type === "file") {
|
|
|
|
download_frame.src = fs_path_url(nav.base.path) + "?attach"
|
|
|
|
} else if (nav.base.type === "dir") {
|
|
|
|
download_frame.src = fs_path_url(nav.base.path) + "?bulk_download"
|
2024-05-08 18:29:59 +02:00
|
|
|
}
|
2020-12-01 23:01:21 +01:00
|
|
|
}
|
2020-11-11 00:00:54 +01:00
|
|
|
</script>
|
|
|
|
|
2020-12-01 23:01:21 +01:00
|
|
|
<svelte:window on:keydown={keydown} />
|
2020-11-11 00:00:54 +01:00
|
|
|
|
2024-04-11 19:33:26 +02:00
|
|
|
<div bind:this={file_viewer} class="file_viewer">
|
2023-05-17 15:34:56 +02:00
|
|
|
<div class="headerbar">
|
2024-03-12 17:53:53 +01:00
|
|
|
<Menu/>
|
2024-08-09 13:02:07 +02:00
|
|
|
<Breadcrumbs nav={nav}/>
|
2020-11-11 00:00:54 +01:00
|
|
|
</div>
|
|
|
|
|
2023-05-25 17:06:17 +02:00
|
|
|
<div class="viewer_area">
|
2023-11-15 15:50:54 +01:00
|
|
|
<Toolbar
|
2023-11-16 12:17:36 +01:00
|
|
|
bind:this={toolbar}
|
2024-08-09 13:02:07 +02:00
|
|
|
nav={nav}
|
2024-04-11 19:33:26 +02:00
|
|
|
file_viewer={file_viewer}
|
2025-02-03 16:29:26 +01:00
|
|
|
file_preview={file_preview}
|
2023-11-15 15:50:54 +01:00
|
|
|
bind:details_visible={details_visible}
|
|
|
|
edit_window={edit_window}
|
|
|
|
bind:edit_visible={edit_visible}
|
|
|
|
on:download={download}
|
|
|
|
/>
|
|
|
|
|
2024-02-15 18:52:46 +01:00
|
|
|
<div class="file_preview">
|
2024-11-14 16:14:58 +01:00
|
|
|
<FilePreview
|
|
|
|
bind:this={file_preview}
|
|
|
|
nav={nav}
|
|
|
|
upload_widget={upload_widget}
|
|
|
|
edit_window={edit_window}
|
|
|
|
on:open_sibling={e => nav.open_sibling(e.detail)}
|
|
|
|
on:download={download}
|
2025-02-03 16:29:26 +01:00
|
|
|
on:details={() => details_visible = !details_visible}
|
2024-11-14 16:14:58 +01:00
|
|
|
/>
|
2023-05-25 17:06:17 +02:00
|
|
|
</div>
|
2020-11-11 00:00:54 +01:00
|
|
|
</div>
|
|
|
|
|
2024-09-05 17:28:31 +02:00
|
|
|
{#if $nav.context.premium_transfer === false}
|
|
|
|
<div class="download_limit">
|
|
|
|
{#if $stats.limits.transfer_limit_used > $stats.limits.transfer_limit}
|
|
|
|
<div class="highlight_yellow">
|
|
|
|
Your free download limit has been used up and your download
|
|
|
|
speed has been limited to 1 MiB/s. <a href="/#pro"
|
|
|
|
target="_blank">Upgrade to premium</a> to continue fast
|
|
|
|
downloading
|
|
|
|
</div>
|
|
|
|
{:else}
|
|
|
|
<TransferLimit/>
|
|
|
|
{/if}
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
|
2020-11-11 00:00:54 +01:00
|
|
|
<!-- This frame will load the download URL when a download button is pressed -->
|
2023-05-17 15:34:56 +02:00
|
|
|
<iframe
|
|
|
|
bind:this={download_frame}
|
|
|
|
title="Frame for downloading files"
|
|
|
|
style="display: none; width: 1px; height: 1px;">
|
|
|
|
</iframe>
|
|
|
|
|
2024-08-09 13:47:10 +02:00
|
|
|
<DetailsWindow nav={nav} bind:visible={details_visible} />
|
|
|
|
|
|
|
|
<EditWindow nav={nav} bind:this={edit_window} bind:visible={edit_visible} />
|
|
|
|
|
2024-09-10 18:51:13 +02:00
|
|
|
<!-- This one is included at the highest level so uploads can keep running
|
|
|
|
even when the user navigates to a different directory -->
|
|
|
|
<FSUploadWidget nav={nav} bind:this={upload_widget} />
|
2024-08-09 13:47:10 +02:00
|
|
|
|
|
|
|
<LoadingIndicator loading={$loading}/>
|
2024-02-15 18:52:46 +01:00
|
|
|
</div>
|
2020-11-11 00:00:54 +01:00
|
|
|
|
|
|
|
<style>
|
2024-02-15 18:52:46 +01:00
|
|
|
:global(*) {
|
2024-11-14 16:14:58 +01:00
|
|
|
transition: background-color 0.2s,
|
|
|
|
border 0.2s,
|
|
|
|
border-top 0.2s,
|
|
|
|
border-right 0.2s,
|
|
|
|
border-bottom 0.2s,
|
|
|
|
border-left 0.2s,
|
|
|
|
color 0.2s;
|
2024-02-15 18:52:46 +01:00
|
|
|
}
|
|
|
|
|
2020-11-11 00:00:54 +01:00
|
|
|
/* Viewer container */
|
|
|
|
.file_viewer {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
right: 0;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
2023-11-15 15:50:54 +01:00
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
2020-11-11 00:00:54 +01:00
|
|
|
overflow: hidden;
|
2024-02-15 18:52:46 +01:00
|
|
|
|
|
|
|
/* Force some variable usage that is normally out of scope */
|
|
|
|
color: var(--body_text_color);
|
2024-05-30 12:28:42 +02:00
|
|
|
|
|
|
|
background-image: var(--background_image, var(--background_pattern));
|
|
|
|
background-color: var(--background_pattern_color);
|
|
|
|
background-size: var(--background_image_size, initial);
|
|
|
|
background-position: var(--background_image_position, initial);
|
|
|
|
background-repeat: var(--background_image_repeat, repeat);
|
2020-11-11 00:00:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Headerbar (row 1) */
|
2023-05-17 15:34:56 +02:00
|
|
|
.headerbar {
|
2023-11-15 15:50:54 +01:00
|
|
|
flex: 0 0 0;
|
2020-11-11 00:00:54 +01:00
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
text-align: left;
|
|
|
|
box-shadow: none;
|
2024-05-30 12:28:42 +02:00
|
|
|
background-color: var(--shaded_background);
|
2024-11-19 15:31:51 +01:00
|
|
|
backdrop-filter: blur(4px);
|
2020-11-11 00:00:54 +01:00
|
|
|
}
|
|
|
|
|
2023-11-15 15:50:54 +01:00
|
|
|
/* File preview area (row 2) */
|
|
|
|
.viewer_area {
|
|
|
|
flex: 1 1 0;
|
2020-11-11 00:00:54 +01:00
|
|
|
display: flex;
|
2020-11-11 23:45:52 +01:00
|
|
|
flex-direction: row;
|
2023-11-15 15:50:54 +01:00
|
|
|
overflow: hidden;
|
2020-11-11 00:00:54 +01:00
|
|
|
}
|
2024-02-16 21:07:01 +01:00
|
|
|
|
2024-09-05 17:28:31 +02:00
|
|
|
/* Download limit gauge (row 3) */
|
|
|
|
.download_limit {
|
|
|
|
flex: 0 0 auto;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
text-align: center;
|
|
|
|
background-color: var(--shaded_background);
|
2024-11-19 15:31:51 +01:00
|
|
|
backdrop-filter: blur(4px);
|
2024-09-05 17:28:31 +02:00
|
|
|
}
|
|
|
|
|
2024-02-16 21:07:01 +01:00
|
|
|
/* This max-width needs to be synced with the .toolbar max-width in
|
|
|
|
Toolbar.svelte and the .label max-width in FileStats.svelte */
|
2025-01-27 22:54:47 +01:00
|
|
|
@media (max-width: 1000px) {
|
2023-11-15 15:50:54 +01:00
|
|
|
.viewer_area {
|
|
|
|
flex-direction: column-reverse;
|
2020-11-11 00:00:54 +01:00
|
|
|
}
|
|
|
|
}
|
2023-05-25 17:06:17 +02:00
|
|
|
|
|
|
|
.file_preview {
|
2023-11-15 15:50:54 +01:00
|
|
|
flex: 1 1 0;
|
|
|
|
overflow: auto;
|
2024-05-30 12:28:42 +02:00
|
|
|
border: 1px solid var(--separator);
|
2023-05-25 17:06:17 +02:00
|
|
|
}
|
2020-11-11 00:00:54 +01:00
|
|
|
</style>
|