225 lines
5.1 KiB
Svelte
225 lines
5.1 KiB
Svelte
<script>
|
|
import { onMount } from 'svelte';
|
|
import PixeldrainLogo from '../util/PixeldrainLogo.svelte';
|
|
import LoadingIndicator from '../util/LoadingIndicator.svelte';
|
|
import EditWindow from './EditWindow.svelte';
|
|
import { fs_file_url } from './FilesystemUtil';
|
|
import Toolbar from './Toolbar.svelte';
|
|
import Breadcrumbs from './Breadcrumbs.svelte';
|
|
import DetailsWindow from './DetailsWindow.svelte';
|
|
import Navigator from './Navigator.svelte';
|
|
import FilePreview from './viewers/FilePreview.svelte';
|
|
|
|
let toolbar_visible = (window.innerWidth > 600)
|
|
let download_frame
|
|
let details_visible = false
|
|
let edit_window
|
|
let edit_visible = false
|
|
|
|
let navigator
|
|
let state = {
|
|
path: window.initial_node.path,
|
|
base_index: window.initial_node.base_index,
|
|
children: window.initial_node.children,
|
|
permissions: window.initial_node.permissions,
|
|
|
|
// Shortcuts
|
|
base: window.initial_node.path[window.initial_node.base_index],
|
|
root: window.initial_node.path[0],
|
|
|
|
// Passwords for accessing this bucket. Passwords are not always required
|
|
// but sometimes they are
|
|
read_password: "",
|
|
write_password: "",
|
|
|
|
// These are used to navigate forward and backward within a directory (using
|
|
// the previous and next buttons on the toolbar). The cached siblings will
|
|
// be used so that we don't need to make an extra request to the parent
|
|
// directory. The siblings_path variable is used to verify that the parent
|
|
// directory is still the same. If it's sifferent the siblings array is not
|
|
// used
|
|
siblings_path: "",
|
|
siblings: null,
|
|
|
|
// Root path of the bucket. Used for navigation by prepending it to a file
|
|
// path
|
|
path_root: "/d/"+window.initial_node.path[0].id,
|
|
loading: true,
|
|
viewer_type: "",
|
|
shuffle: false,
|
|
}
|
|
|
|
onMount(() => navigator.open_node(window.initial_node, false))
|
|
|
|
const keydown = e => {
|
|
if (e.ctrlKey || e.altKey || e.metaKey) {
|
|
return // prevent custom shortcuts from interfering with system shortcuts
|
|
}
|
|
if (document.activeElement.type && document.activeElement.type === "text") {
|
|
return // Prevent shortcuts from interfering with input fields
|
|
}
|
|
|
|
switch (e.key) {
|
|
case "i":
|
|
details_visible = !details_visible
|
|
break;
|
|
case "e":
|
|
if (edit_visible) {
|
|
edit_visible = false
|
|
} else {
|
|
edit_window.edit(state.base)
|
|
}
|
|
break;
|
|
case "s":
|
|
download()
|
|
break;
|
|
case "r":
|
|
state.shuffle = !state.shuffle
|
|
break;
|
|
case "a":
|
|
case "ArrowLeft":
|
|
navigator.open_sibling(-1)
|
|
break;
|
|
case "d":
|
|
case "ArrowRight":
|
|
navigator.open_sibling(1)
|
|
break;
|
|
}
|
|
};
|
|
|
|
const download = () => {
|
|
download_frame.src = fs_file_url(state.root.id, state.base.path) + "?attach"
|
|
}
|
|
</script>
|
|
|
|
<svelte:window on:keydown={keydown} />
|
|
|
|
<LoadingIndicator loading={state.loading}/>
|
|
|
|
<Navigator bind:this={navigator} bind:state/>
|
|
|
|
<div class="file_viewer">
|
|
<div class="headerbar">
|
|
<button
|
|
on:click={() => toolbar_visible = !toolbar_visible}
|
|
class="button_toggle_toolbar round"
|
|
class:button_highlight={toolbar_visible}
|
|
>
|
|
<i class="icon">menu</i>
|
|
</button>
|
|
<a href="/" id="button_home" class="button button_home round">
|
|
<PixeldrainLogo style="height: 1.6em; width: 1.6em; margin: 0 0.2em 0 0; color: currentColor;"/>
|
|
</a>
|
|
<div class="breadcrumbs">
|
|
<Breadcrumbs state={state} navigator={navigator}/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="file_preview">
|
|
<Toolbar
|
|
visible={toolbar_visible}
|
|
navigator={navigator}
|
|
state={state}
|
|
bind:details_visible={details_visible}
|
|
edit_window={edit_window}
|
|
bind:edit_visible={edit_visible}
|
|
on:download={download}
|
|
/>
|
|
|
|
<FilePreview
|
|
navigator={navigator}
|
|
state={state}
|
|
toolbar_visible={toolbar_visible}
|
|
edit_window={edit_window}
|
|
on:loading={e => {state.loading = e.detail}}
|
|
/>
|
|
</div>
|
|
|
|
<!-- 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
|
|
state={state}
|
|
bind:visible={details_visible}
|
|
/>
|
|
|
|
<EditWindow
|
|
bind:this={edit_window}
|
|
bind:visible={edit_visible}
|
|
bucket={state.root.id}
|
|
on:navigate={e => navigator.navigate(e.path, e.push_history)}
|
|
/>
|
|
</div>
|
|
|
|
<style>
|
|
/* Viewer container */
|
|
.file_viewer {
|
|
position: absolute;
|
|
display: flex;
|
|
flex-direction: column;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
overflow: hidden;
|
|
background: var(--body_background);
|
|
}
|
|
|
|
/* Headerbar (row 1) */
|
|
.headerbar {
|
|
flex-grow: 0;
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
flex-direction: row;
|
|
text-align: left;
|
|
z-index: 10;
|
|
box-shadow: none;
|
|
padding: 4px;
|
|
}
|
|
|
|
/* Headerbar components */
|
|
.headerbar > * {
|
|
flex-grow: 0;
|
|
flex-shrink: 0;
|
|
margin-left: 4px;
|
|
margin-right: 4px;
|
|
display: inline;
|
|
align-self: center;
|
|
}
|
|
.button_toggle_toolbar > .icon {
|
|
font-size: 1.6em;
|
|
}
|
|
.breadcrumbs {
|
|
flex-grow: 1;
|
|
flex-shrink: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
flex-direction: row;
|
|
}
|
|
.button_home::after {
|
|
content: "pixeldrain";
|
|
}
|
|
@media (max-width: 600px) {
|
|
.button_home::after {
|
|
content: "pd";
|
|
}
|
|
}
|
|
/* File preview area (row 2) */
|
|
.file_preview {
|
|
flex-grow: 1;
|
|
flex-shrink: 1;
|
|
position: relative;
|
|
display: inline-block;
|
|
width: auto;
|
|
height: auto;
|
|
margin: 0;
|
|
z-index: 9;
|
|
}
|
|
</style>
|