Change filesystem navigator into a class with a svelte store implementation
This commit is contained in:
@@ -4,8 +4,7 @@ import { fs_encode_path, fs_node_icon, fs_path_url } from '../FilesystemUtil';
|
||||
import FileTitle from '../../file_viewer/viewers/FileTitle.svelte';
|
||||
import TextBlock from '../../file_viewer/viewers/TextBlock.svelte';
|
||||
|
||||
export let fs_navigator
|
||||
export let state
|
||||
export let nav
|
||||
let player
|
||||
let playing = false
|
||||
let media_session = false
|
||||
@@ -18,13 +17,13 @@ export const toggle_playback = () => {
|
||||
export const update = async () => {
|
||||
if (media_session) {
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: state.base.name,
|
||||
title: nav.base.name,
|
||||
artist: "pixeldrain",
|
||||
album: "unknown",
|
||||
});
|
||||
}
|
||||
|
||||
siblings = await fs_navigator.get_siblings()
|
||||
siblings = await nav.get_siblings()
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@@ -33,30 +32,30 @@ onMount(() => {
|
||||
navigator.mediaSession.setActionHandler('play', () => player.play());
|
||||
navigator.mediaSession.setActionHandler('pause', () => player.pause());
|
||||
navigator.mediaSession.setActionHandler('stop', () => player.stop());
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => fs_navigator.open_sibling(-1));
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => fs_navigator.open_sibling(1));
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => nav.open_sibling(-1));
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => nav.open_sibling(1));
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<FileTitle title={state.base.name}/>
|
||||
<FileTitle title={$nav.base.name}/>
|
||||
|
||||
<TextBlock width="1000px">
|
||||
<audio
|
||||
bind:this={player}
|
||||
class="player"
|
||||
src={fs_path_url(state.base.path)}
|
||||
src={fs_path_url($nav.base.path)}
|
||||
autoplay="autoplay"
|
||||
controls="controls"
|
||||
on:pause={() => playing = false }
|
||||
on:play={() => playing = true }
|
||||
on:ended={() => fs_navigator.open_sibling(1) }>
|
||||
on:ended={() => nav.open_sibling(1) }>
|
||||
<track kind="captions"/>
|
||||
</audio>
|
||||
<div style="text-align: center;">
|
||||
<button on:click={() => fs_navigator.open_sibling(-1) }><i class="icon">skip_previous</i></button>
|
||||
<button on:click={() => nav.open_sibling(-1) }><i class="icon">skip_previous</i></button>
|
||||
<button on:click={() => player.currentTime -= 10 }><i class="icon">replay_10</i></button>
|
||||
<button on:click={toggle_playback}>
|
||||
{#if playing}
|
||||
@@ -66,17 +65,17 @@ onMount(() => {
|
||||
{/if}
|
||||
</button>
|
||||
<button on:click={() => player.currentTime += 10 }><i class="icon">forward_10</i></button>
|
||||
<button on:click={() => fs_navigator.open_sibling(1) }><i class="icon">skip_next</i></button>
|
||||
<button on:click={() => nav.open_sibling(1) }><i class="icon">skip_next</i></button>
|
||||
</div>
|
||||
|
||||
<h2>Tracklist</h2>
|
||||
{#each siblings as sibling (sibling.path)}
|
||||
<a
|
||||
href={"/d"+fs_encode_path(sibling.path)}
|
||||
on:click|preventDefault={() => fs_navigator.navigate(sibling.path, true)}
|
||||
on:click|preventDefault={() => nav.navigate(sibling.path, true)}
|
||||
class="node"
|
||||
>
|
||||
{#if sibling.path === state.base.path}
|
||||
{#if sibling.path === $nav.base.path}
|
||||
<i class="play_arrow icon">play_arrow</i>
|
||||
{:else}
|
||||
<img src={fs_node_icon(sibling, 64, 64)} class="node_icon" alt="icon"/>
|
||||
|
@@ -5,15 +5,15 @@ import { fs_thumbnail_url } from "../FilesystemUtil";
|
||||
import TextBlock from "../../file_viewer/viewers/TextBlock.svelte";
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
</script>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<h1>{state.base.name}</h1>
|
||||
<h1>{$nav.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_thumbnail_url(state.base.path, 256, 256)}>
|
||||
Type: {state.base.file_type}<br/>
|
||||
<IconBlock icon_href={fs_thumbnail_url($nav.base.path, 256, 256)}>
|
||||
Type: {$nav.base.file_type}<br/>
|
||||
No preview is available for this file type. Download to view it locally.
|
||||
<br/>
|
||||
<button class="button_highlight" on:click={() => {dispatch("download")}}>
|
||||
@@ -22,7 +22,7 @@ export let state
|
||||
</button>
|
||||
</IconBlock>
|
||||
|
||||
{#if state.base.path === "/me/.search_index.gz"}
|
||||
{#if $nav.base.path === "/me/.search_index.gz"}
|
||||
<TextBlock>
|
||||
<p>
|
||||
Congratulations! You have found the search index. One of the
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { tick } from "svelte";
|
||||
import { onMount, tick } from "svelte";
|
||||
import Spinner from "../../util/Spinner.svelte";
|
||||
import { fs_node_type } from "../FilesystemUtil";
|
||||
import FileManager from "../filemanager/FileManager.svelte";
|
||||
@@ -13,25 +13,25 @@ import Torrent from "./Torrent.svelte";
|
||||
import Zip from "./Zip.svelte";
|
||||
import CustomBanner from "./CustomBanner.svelte";
|
||||
|
||||
export let fs_navigator
|
||||
export let nav
|
||||
export let edit_window
|
||||
|
||||
export let state
|
||||
let viewer
|
||||
let viewer_type = ""
|
||||
let last_path = ""
|
||||
|
||||
$: state_update(state.base)
|
||||
const state_update = async (base) => {
|
||||
if (base.path === last_path) {
|
||||
onMount(() => nav.subscribe(state_update))
|
||||
|
||||
const state_update = async () => {
|
||||
if (!nav.initialized || nav.base.path === last_path) {
|
||||
return
|
||||
}
|
||||
last_path = base.path
|
||||
last_path = nav.base.path
|
||||
|
||||
// Update the viewer area with the right viewer type
|
||||
viewer_type = fs_node_type(base)
|
||||
viewer_type = fs_node_type(nav.base)
|
||||
|
||||
console.debug("Previewing file", base, "viewer type", viewer_type)
|
||||
console.debug("Previewing file", nav.base, "viewer type", viewer_type)
|
||||
|
||||
// Render the viewer component and set the file type
|
||||
await tick()
|
||||
@@ -52,40 +52,34 @@ export const toggle_playback = () => {
|
||||
<Spinner></Spinner>
|
||||
</div>
|
||||
{:else if viewer_type === "dir"}
|
||||
<FileManager
|
||||
fs_navigator={fs_navigator}
|
||||
state={state}
|
||||
edit_window={edit_window}
|
||||
on:loading
|
||||
on:upload_picker
|
||||
>
|
||||
<CustomBanner path={state.path}/>
|
||||
<FileManager nav={nav} edit_window={edit_window} on:loading on:upload_picker>
|
||||
<CustomBanner path={$nav.path}/>
|
||||
</FileManager>
|
||||
{:else if viewer_type === "audio"}
|
||||
<Audio state={state} bind:this={viewer} fs_navigator={fs_navigator}>
|
||||
<CustomBanner path={state.path}/>
|
||||
<Audio nav={nav} bind:this={viewer}>
|
||||
<CustomBanner path={$nav.path}/>
|
||||
</Audio>
|
||||
{:else if viewer_type === "image"}
|
||||
<Image state={state} bind:this={viewer} on:open_sibling/>
|
||||
<Image nav={nav} bind:this={viewer}/>
|
||||
{:else if viewer_type === "video"}
|
||||
<Video state={state} bind:this={viewer} on:open_sibling/>
|
||||
<Video nav={nav} bind:this={viewer} on:open_sibling/>
|
||||
{:else if viewer_type === "pdf"}
|
||||
<Pdf state={state}/>
|
||||
<Pdf nav={nav}/>
|
||||
{:else if viewer_type === "text"}
|
||||
<Text state={state} bind:this={viewer}>
|
||||
<CustomBanner path={state.path}/>
|
||||
<Text nav={nav} bind:this={viewer}>
|
||||
<CustomBanner path={$nav.path}/>
|
||||
</Text>
|
||||
{:else if viewer_type === "torrent"}
|
||||
<Torrent state={state} bind:this={viewer} on:loading on:download>
|
||||
<CustomBanner path={state.path}/>
|
||||
<Torrent nav={nav} bind:this={viewer} on:loading on:download>
|
||||
<CustomBanner path={$nav.path}/>
|
||||
</Torrent>
|
||||
{:else if viewer_type === "zip"}
|
||||
<Zip state={state} bind:this={viewer} on:loading on:download>
|
||||
<CustomBanner path={state.path}/>
|
||||
<Zip nav={nav} bind:this={viewer} on:loading on:download>
|
||||
<CustomBanner path={$nav.path}/>
|
||||
</Zip>
|
||||
{:else}
|
||||
<File state={state} on:download>
|
||||
<CustomBanner path={state.path}/>
|
||||
<File nav={nav} on:download>
|
||||
<CustomBanner path={$nav.path}/>
|
||||
</File>
|
||||
{/if}
|
||||
|
||||
|
@@ -5,7 +5,7 @@ import { fs_path_url } from "../FilesystemUtil";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
let container
|
||||
let zoom = false
|
||||
let x, y = 0
|
||||
@@ -64,8 +64,8 @@ const mouseup = (e) => {
|
||||
class:zoom
|
||||
use:swipe_nav={!zoom}
|
||||
on:style={e => swipe_style = e.detail}
|
||||
on:prev={() => dispatch("open_sibling", -1)}
|
||||
on:next={() => dispatch("open_sibling", 1)}
|
||||
on:prev={() => nav.open_sibling(-1)}
|
||||
on:next={() => nav.open_sibling(1)}
|
||||
>
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<img
|
||||
@@ -77,7 +77,7 @@ const mouseup = (e) => {
|
||||
class="image"
|
||||
class:zoom
|
||||
style={swipe_style}
|
||||
src={fs_path_url(state.base.path)}
|
||||
src={fs_path_url($nav.base.path)}
|
||||
alt="no description available" />
|
||||
</div>
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<script>
|
||||
import { fs_path_url } from "../FilesystemUtil";
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
</script>
|
||||
|
||||
<iframe
|
||||
class="container"
|
||||
src={"/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(fs_path_url(state.base.path))}
|
||||
src={"/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(fs_path_url($nav.base.path))}
|
||||
title="PDF viewer">
|
||||
</iframe>
|
||||
|
||||
|
@@ -2,26 +2,25 @@
|
||||
import { tick } from "svelte";
|
||||
import { fs_path_url } from "../FilesystemUtil";
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
let text_type = "text"
|
||||
|
||||
export const update = () => {
|
||||
const file = state.base
|
||||
console.debug("Loading text file", file.name)
|
||||
console.debug("Loading text file", nav.base.name)
|
||||
|
||||
if (file.size > 1 << 21) { // File larger than 2 MiB
|
||||
if (nav.base.size > 1 << 21) { // File larger than 2 MiB
|
||||
text_pre.innerText = "File is too large to view online.\nPlease download and view it locally."
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
file.file_type.startsWith("text/markdown") ||
|
||||
file.name.endsWith(".md") ||
|
||||
file.name.endsWith(".markdown")
|
||||
nav.base.file_type.startsWith("text/markdown") ||
|
||||
nav.base.name.endsWith(".md") ||
|
||||
nav.base.name.endsWith(".markdown")
|
||||
) {
|
||||
markdown(file)
|
||||
markdown(nav.base)
|
||||
} else {
|
||||
text(file)
|
||||
text(nav.base)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@ import CopyButton from "../../layout/CopyButton.svelte";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
|
||||
let status = "loading"
|
||||
|
||||
@@ -18,7 +18,7 @@ export const update = async () => {
|
||||
dispatch("loading", true)
|
||||
|
||||
try {
|
||||
let resp = await fetch(fs_path_url(state.base.path)+"?torrent_info")
|
||||
let resp = await fetch(fs_path_url(nav.base.path)+"?torrent_info")
|
||||
|
||||
if (resp.status >= 400) {
|
||||
let json = await resp.json()
|
||||
@@ -63,9 +63,9 @@ let magnet = ""
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<h1>{state.base.name}</h1>
|
||||
<h1>{$nav.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||
<IconBlock icon_href={fs_node_icon($nav.base, 256, 256)}>
|
||||
{#if status === "finished"}
|
||||
Created by: {torrent.created_by}<br/>
|
||||
Comment: {torrent.comment}<br/>
|
||||
|
@@ -3,7 +3,7 @@ import { onMount, createEventDispatcher, tick } from "svelte";
|
||||
import { fs_path_url } from "../FilesystemUtil";
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
|
||||
// Used to detect when the file path changes
|
||||
let last_path = ""
|
||||
@@ -17,20 +17,20 @@ let loop = false
|
||||
export const update = async () => {
|
||||
if (media_session) {
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: state.base.name,
|
||||
title: nav.base.name,
|
||||
artist: "pixeldrain",
|
||||
album: "unknown",
|
||||
});
|
||||
console.debug("Updating media session")
|
||||
}
|
||||
|
||||
loop = state.base.name.includes(".loop.")
|
||||
loop = nav.base.name.includes(".loop.")
|
||||
|
||||
// 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
|
||||
// make sure that the video is unloaded and loaded when the ID changes
|
||||
if (state.base.path != last_path) {
|
||||
last_path = state.base.path
|
||||
if (nav.base.path != last_path) {
|
||||
last_path = nav.base.path
|
||||
loaded = false
|
||||
await tick()
|
||||
loaded = true
|
||||
@@ -75,9 +75,9 @@ const fullscreen = () => {
|
||||
|
||||
<div class="container">
|
||||
{#if
|
||||
state.base.file_type === "video/x-matroska" ||
|
||||
state.base.file_type === "video/quicktime" ||
|
||||
state.base.file_type === "video/x-ms-asf"
|
||||
$nav.base.file_type === "video/x-matroska" ||
|
||||
$nav.base.file_type === "video/quicktime" ||
|
||||
$nav.base.file_type === "video/x-ms-asf"
|
||||
}
|
||||
<div class="compatibility_warning">
|
||||
This video file type is not compatible with every web
|
||||
@@ -100,7 +100,7 @@ const fullscreen = () => {
|
||||
on:play={() => playing = true }
|
||||
on:ended={() => dispatch("open_sibling", 1)}
|
||||
>
|
||||
<source src={fs_path_url(state.base.path)} type={state.base.file_type} />
|
||||
<source src={fs_path_url($nav.base.path)} type={$nav.base.file_type} />
|
||||
</video>
|
||||
{/if}
|
||||
</div>
|
||||
|
@@ -8,7 +8,7 @@ import { fs_node_icon, fs_path_url } from "../FilesystemUtil";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
|
||||
let status = "loading"
|
||||
|
||||
@@ -23,14 +23,14 @@ let archive_type = ""
|
||||
export const update = async () => {
|
||||
dispatch("loading", true)
|
||||
|
||||
if (state.base.file_type === "application/zip") {
|
||||
if (nav.base.file_type === "application/zip") {
|
||||
archive_type = "zip"
|
||||
} else if (state.base.file_type === "application/x-7z-compressed") {
|
||||
} else if (nav.base.file_type === "application/x-7z-compressed") {
|
||||
archive_type = "7z"
|
||||
}
|
||||
|
||||
try {
|
||||
let resp = await fetch(fs_path_url(state.base.path)+"?zip_info")
|
||||
let resp = await fetch(fs_path_url(nav.base.path)+"?zip_info")
|
||||
|
||||
if (resp.status >= 400) {
|
||||
status = "parse_failed"
|
||||
@@ -43,11 +43,11 @@ export const update = async () => {
|
||||
// downloaded. If so then we set the download URL for each file
|
||||
if (zip.properties && zip.properties.includes("read_individual_files")) {
|
||||
// Set the download URL for each file in the zip
|
||||
recursive_set_url(fs_path_url(state.base.path)+"?zip_file=", zip)
|
||||
recursive_set_url(fs_path_url(nav.base.path)+"?zip_file=", zip)
|
||||
}
|
||||
|
||||
uncomp_size = recursive_size(zip)
|
||||
comp_ratio = (uncomp_size / state.base.file_size)
|
||||
comp_ratio = (uncomp_size / nav.base.file_size)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
} finally {
|
||||
@@ -85,18 +85,18 @@ const recursive_size = (file) => {
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<h1>{state.base.name}</h1>
|
||||
<h1>{$nav.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||
<IconBlock icon_href={fs_node_icon($nav.base, 256, 256)}>
|
||||
{#if archive_type === "7z"}
|
||||
This is a 7-zip archive. You will need
|
||||
<a href="https://www.7-zip.org/">7-zip</a> or compatible software to
|
||||
extract it<br/>
|
||||
{/if}
|
||||
|
||||
Compressed size: {formatDataVolume(state.base.file_size, 3)}<br/>
|
||||
Compressed size: {formatDataVolume($nav.base.file_size, 3)}<br/>
|
||||
Uncompressed size: {formatDataVolume(zip.size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
||||
Uploaded on: {formatDate(state.base.created, true, true, true)}
|
||||
Uploaded on: {formatDate($nav.base.created, true, true, true)}
|
||||
<br/>
|
||||
<button class="button_highlight" on:click={() => {dispatch("download")}}>
|
||||
<i class="icon">download</i>
|
||||
|
Reference in New Issue
Block a user