Convert multiple pages into SPA
This commit is contained in:
@@ -1,20 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import LoadingIndicator from "util/LoadingIndicator.svelte";
|
||||
import EditWindow from "./edit_window/EditWindow.svelte";
|
||||
import Toolbar from "./Toolbar.svelte";
|
||||
import Breadcrumbs from "./Breadcrumbs.svelte";
|
||||
import DetailsWindow from "./DetailsWindow.svelte";
|
||||
import FilePreview from "./viewers/FilePreview.svelte";
|
||||
import FSUploadWidget from "./upload_widget/FSUploadWidget.svelte";
|
||||
import { fs_download, type FSPath } from "./FilesystemAPI";
|
||||
import Menu from "./Menu.svelte";
|
||||
import { fs_download, type FSPath } from "lib/FilesystemAPI";
|
||||
import { FSNavigator } from "./FSNavigator"
|
||||
import { writable } from "svelte/store";
|
||||
import { css_from_path } from "filesystem/edit_window/Branding";
|
||||
import AffiliatePrompt from "user_home/AffiliatePrompt.svelte";
|
||||
import { current_page_store } from "wrap/RouterStore";
|
||||
|
||||
let file_viewer: HTMLDivElement
|
||||
let file_preview: FilePreview
|
||||
let toolbar: Toolbar
|
||||
let upload_widget: FSUploadWidget
|
||||
@@ -22,25 +19,37 @@ let details_visible = false
|
||||
let edit_window: EditWindow
|
||||
let edit_visible = false
|
||||
|
||||
const loading = writable(true)
|
||||
const nav = new FSNavigator(true)
|
||||
|
||||
onMount(() => {
|
||||
nav.loading = loading
|
||||
nav.open_node((window as any).initial_node as FSPath, false)
|
||||
if ((window as any).intial_node !== undefined) {
|
||||
console.debug("Loading initial node")
|
||||
nav.open_node((window as any).initial_node as FSPath, false)
|
||||
} else {
|
||||
console.debug("No initial node, fetching path", window.location.pathname)
|
||||
nav.navigate(decodeURI(window.location.pathname).replace(/^\/d/, ""), false)
|
||||
}
|
||||
|
||||
const page_sub = current_page_store.subscribe(() => {
|
||||
console.debug("Caught page transition to", window.location.pathname)
|
||||
nav.navigate(decodeURI(window.location.pathname).replace(/^\/d/, ""), false)
|
||||
})
|
||||
|
||||
// Subscribe to navigation updates. This function returns a deconstructor
|
||||
// which we can conveniently return from our mount function as well
|
||||
return nav.subscribe(nav => {
|
||||
const nav_sub = nav.subscribe(nav => {
|
||||
if (!nav.initialized) {
|
||||
return
|
||||
}
|
||||
|
||||
// Custom CSS rules for the whole viewer
|
||||
document.documentElement.style = css_from_path(nav.path)
|
||||
|
||||
loading.set(false)
|
||||
})
|
||||
return () => {
|
||||
page_sub()
|
||||
nav_sub()
|
||||
document.documentElement.style = ""
|
||||
}
|
||||
})
|
||||
|
||||
const keydown = (e: KeyboardEvent) => {
|
||||
@@ -127,50 +136,41 @@ const keydown = (e: KeyboardEvent) => {
|
||||
|
||||
<svelte:window on:keydown={keydown} />
|
||||
|
||||
<div bind:this={file_viewer} class="file_viewer">
|
||||
<div class="headerbar">
|
||||
<Menu/>
|
||||
<Breadcrumbs nav={nav}/>
|
||||
</div>
|
||||
<div class="filesystem">
|
||||
<Breadcrumbs nav={nav}/>
|
||||
|
||||
<div class="viewer_area">
|
||||
<Toolbar
|
||||
bind:this={toolbar}
|
||||
<div class="file_preview">
|
||||
<FilePreview
|
||||
bind:this={file_preview}
|
||||
nav={nav}
|
||||
file_viewer={file_viewer}
|
||||
file_preview={file_preview}
|
||||
bind:details_visible={details_visible}
|
||||
upload_widget={upload_widget}
|
||||
edit_window={edit_window}
|
||||
bind:edit_visible={edit_visible}
|
||||
on:open_sibling={e => nav.open_sibling(e.detail)}
|
||||
on:download={() => fs_download(nav.base)}
|
||||
on:details={() => details_visible = !details_visible}
|
||||
/>
|
||||
|
||||
<div class="file_preview">
|
||||
<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={() => fs_download(nav.base)}
|
||||
on:details={() => details_visible = !details_visible}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DetailsWindow nav={nav} bind:visible={details_visible} />
|
||||
|
||||
<EditWindow nav={nav} bind:this={edit_window} bind:visible={edit_visible} />
|
||||
|
||||
<!-- 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} />
|
||||
|
||||
<AffiliatePrompt/>
|
||||
|
||||
<LoadingIndicator loading={$loading}/>
|
||||
<Toolbar
|
||||
bind:this={toolbar}
|
||||
nav={nav}
|
||||
bind:details_visible={details_visible}
|
||||
edit_window={edit_window}
|
||||
bind:edit_visible={edit_visible}
|
||||
on:download={() => fs_download(nav.base)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<DetailsWindow nav={nav} bind:visible={details_visible} />
|
||||
|
||||
<EditWindow nav={nav} bind:this={edit_window} bind:visible={edit_visible} />
|
||||
|
||||
<!-- 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} />
|
||||
|
||||
<AffiliatePrompt/>
|
||||
|
||||
<style>
|
||||
:global(*) {
|
||||
transition: background-color 0.2s,
|
||||
@@ -183,56 +183,15 @@ const keydown = (e: KeyboardEvent) => {
|
||||
}
|
||||
|
||||
/* Viewer container */
|
||||
.file_viewer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
.filesystem {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
/* Force some variable usage that is normally out of scope */
|
||||
color: var(--body_text_color);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Headerbar (row 1) */
|
||||
.headerbar {
|
||||
flex: 0 0 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
box-shadow: none;
|
||||
background-color: var(--shaded_background);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
/* File preview area (row 2) */
|
||||
.viewer_area {
|
||||
flex: 1 1 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* This max-width needs to be synced with the .toolbar max-width in
|
||||
Toolbar.svelte and the .label max-width in FileStats.svelte */
|
||||
@media (max-width: 1000px) {
|
||||
.viewer_area {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file_preview {
|
||||
flex: 1 1 0;
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
border: 1px solid var(--separator);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user