Update to svelte 5

This commit is contained in:
2025-10-13 16:05:50 +02:00
parent f936e4c0f2
commit 6d89c5ddd9
129 changed files with 2443 additions and 2180 deletions

View File

@@ -1,14 +1,19 @@
<script lang="ts">
import { preventDefault } from 'svelte/legacy';
import { onMount } from 'svelte'
import { fs_path_url, fs_encode_path, fs_node_icon } from "lib/FilesystemAPI"
import TextBlock from "layout/TextBlock.svelte"
import type { FSNavigator } from 'filesystem/FSNavigator';
export let nav: FSNavigator
let player: HTMLAudioElement
let playing = false
let { nav, children }: {
nav: FSNavigator;
children?: import('svelte').Snippet;
} = $props();
let player: HTMLAudioElement = $state()
let playing = $state(false)
let media_session = false
let siblings = []
let siblings = $state([])
export const toggle_playback = () => playing ? player.pause() : player.play()
export const toggle_mute = () => player.muted = !player.muted
@@ -47,7 +52,7 @@ onMount(() => {
})
</script>
<slot></slot>
{@render children?.()}
<TextBlock width="1000px">
<audio
@@ -56,30 +61,30 @@ onMount(() => {
src={fs_path_url($nav.base.path)}
autoplay
controls
on:pause={() => playing = false }
on:play={() => playing = true }
on:ended={() => nav.open_sibling(1) }>
onpause={() => playing = false}
onplay={() => playing = true}
onended={() => nav.open_sibling(1)}>
<track kind="captions"/>
</audio>
<div style="text-align: center;">
<button on:click={() => nav.open_sibling(-1) }><i class="icon">skip_previous</i></button>
<button on:click={() => seek(-10) }><i class="icon">replay_10</i></button>
<button on:click={toggle_playback}>
<button onclick={() => nav.open_sibling(-1)}><i class="icon">skip_previous</i></button>
<button onclick={() => seek(-10)}><i class="icon">replay_10</i></button>
<button onclick={toggle_playback}>
{#if playing}
<i class="icon">pause</i>
{:else}
<i class="icon">play_arrow</i>
{/if}
</button>
<button on:click={() => seek(10) }><i class="icon">forward_10</i></button>
<button on:click={() => nav.open_sibling(1) }><i class="icon">skip_next</i></button>
<button onclick={() => seek(10)}><i class="icon">forward_10</i></button>
<button onclick={() => 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={() => nav.navigate(sibling.path, true)}
onclick={preventDefault(() => nav.navigate(sibling.path, true))}
class="node"
>
{#if sibling.path === $nav.base.path}

View File

@@ -1,10 +1,12 @@
<script lang="ts">
export let path = []
import type { FSNode } from 'lib/FilesystemAPI';
import { run } from 'svelte/legacy';
let image_uri: string
let image_link: string
$: update_links(path)
const update_links = (path) => {
let { path = [] }: {path: FSNode[]} = $props();
let image_uri: string = $state()
let image_link: string = $state()
const update_links = (path: FSNode[]) => {
image_uri = null
image_link = null
for (let node of path) {
@@ -18,6 +20,9 @@ const update_links = (path) => {
}
}
}
run(() => {
update_links(path)
});
</script>
{#if image_uri}

View File

@@ -8,10 +8,13 @@ import type { FSNavigator } from "filesystem/FSNavigator";
let dispatch = createEventDispatcher()
export let nav: FSNavigator
let { nav, children }: {
nav: FSNavigator;
children?: import('svelte').Snippet;
} = $props();
</script>
<slot></slot>
{@render children?.()}
<h1>{$nav.base.name}</h1>
@@ -20,11 +23,11 @@ export let nav: FSNavigator
Size: {formatDataVolume($nav.base.file_size, 3)}<br/>
Upload date: {formatDate($nav.base.created, true, true, false)}
<hr/>
<button class="button_highlight" on:click={() => {dispatch("download")}}>
<button class="button_highlight" onclick={() => {dispatch("download")}}>
<i class="icon">download</i>
<span>Download</span>
</button>
<button on:click={() => {dispatch("details")}}>
<button onclick={() => {dispatch("details")}}>
<i class="icon">help</i>
<span>Details</span>
</button>

View File

@@ -16,12 +16,14 @@ import type { FSNavigator } from "filesystem/FSNavigator";
import FsUploadWidget from "filesystem/upload_widget/FSUploadWidget.svelte";
import EditWindow from "filesystem/edit_window/EditWindow.svelte";
export let nav: FSNavigator
export let upload_widget: FsUploadWidget
export let edit_window: EditWindow
let { nav, upload_widget, edit_window }: {
nav: FSNavigator;
upload_widget: FsUploadWidget;
edit_window: EditWindow;
} = $props();
let viewer: any
let viewer_type = ""
let viewer: any = $state()
let viewer_type = $state("")
let last_path = ""
onMount(() => nav.subscribe(state_update))

View File

@@ -6,13 +6,16 @@ import type { FSNavigator } from "filesystem/FSNavigator";
let dispatch = createEventDispatcher();
export let nav: FSNavigator
let container: HTMLDivElement
let zoom = false
let { nav }: {
nav: FSNavigator;
} = $props();
let container: HTMLDivElement = $state()
let zoom = $state(false)
let x = 0, y = 0
let dragging = false
let swipe_prev = true
let swipe_next = true
let swipe_prev = $state(true)
let swipe_next = $state(true)
export const update = async () => {
dispatch("loading", true)
@@ -66,7 +69,7 @@ const mouseup = (e: MouseEvent) => {
}
</script>
<svelte:window on:mousemove={mousemove} on:mouseup={mouseup} />
<svelte:window onmousemove={mousemove} onmouseup={mouseup} />
<div
bind:this={container}
@@ -80,12 +83,12 @@ const mouseup = (e: MouseEvent) => {
on_next: () => nav.open_sibling(1),
}}
>
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<img
on:dblclick={() => {zoom = !zoom}}
on:mousedown={mousedown}
on:load={on_load}
on:error={on_load}
ondblclick={() => {zoom = !zoom}}
onmousedown={mousedown}
onload={on_load}
onerror={on_load}
class="image"
class:zoom
src={fs_path_url($nav.base.path)}

View File

@@ -2,7 +2,9 @@
import { fs_path_url } from "lib/FilesystemAPI";
import type { FSNavigator } from "filesystem/FSNavigator";
export let nav: FSNavigator
let { nav }: {
nav: FSNavigator;
} = $props();
</script>
<iframe

View File

@@ -3,8 +3,12 @@ import { tick } from "svelte";
import { fs_path_url, type FSNode } from "lib/FilesystemAPI";
import type { FSNavigator } from "filesystem/FSNavigator";
export let nav: FSNavigator
let text_type = "text"
let { nav, children }: {
nav: FSNavigator;
children?: import('svelte').Snippet;
} = $props();
let text_type = $state("text")
export const update = () => {
console.debug("Loading text file", nav.base.name)
@@ -25,7 +29,7 @@ export const update = () => {
}
}
let text_pre: HTMLPreElement
let text_pre: HTMLPreElement = $state()
const text = async (file: FSNode) => {
text_type = "text"
await tick()
@@ -42,7 +46,7 @@ const text = async (file: FSNode) => {
})
}
let md_container: HTMLElement
let md_container: HTMLElement = $state()
const markdown = async (file: FSNode) => {
text_type = "markdown"
await tick()
@@ -61,7 +65,7 @@ const markdown = async (file: FSNode) => {
</script>
<div class="container">
<slot></slot>
{@render children?.()}
{#if text_type === "markdown"}
<section bind:this={md_container} class="md">

View File

@@ -1,4 +1,4 @@
<script lang="ts" context="module">
<script lang="ts" module>
export type TorrentInfo = {
trackers: string[]
comment: string,
@@ -26,9 +26,12 @@ import { loading_finish, loading_start } from "lib/Loading";
let dispatch = createEventDispatcher()
export let nav: FSNavigator
let { nav, children }: {
nav: FSNavigator;
children?: import('svelte').Snippet;
} = $props();
let status = "loading"
let status = $state("loading")
export const update = async () => {
try {
@@ -64,11 +67,11 @@ export const update = async () => {
}
}
let torrent: TorrentInfo = {} as TorrentInfo
let magnet = ""
let torrent: TorrentInfo = $state({} as TorrentInfo)
let magnet = $state("")
</script>
<slot></slot>
{@render children?.()}
<h1>{$nav.base.name}</h1>
@@ -93,7 +96,7 @@ let magnet = ""
Torrent file could not be parsed. It may be corrupted.
</p>
{/if}
<button on:click={() => {dispatch("download")}} class="button">
<button onclick={() => {dispatch("download")}} class="button">
<i class="icon">download</i>
<span>Download torrent file</span>
</button>

View File

@@ -1,8 +1,11 @@
<script lang="ts">
import TorrentItem from './TorrentItem.svelte';
import { formatDataVolume } from "util/Formatting";
import type { TorrentFile } from "./Torrent.svelte";
export let item: TorrentFile = {} as TorrentFile
let { item = {} as TorrentFile }: {
item?: TorrentFile;
} = $props();
</script>
<ul class="list_open">
@@ -10,7 +13,7 @@ export let item: TorrentFile = {} as TorrentFile
<li class:list_closed={!child.children}>
{name} ({formatDataVolume(child.size, 3)})<br/>
{#if child.children}
<svelte:self item={child}></svelte:self>
<TorrentItem item={child}></TorrentItem>
{/if}
</li>
{/each}

View File

@@ -5,16 +5,18 @@ import { fs_path_url } from "lib/FilesystemAPI";
import type { FSNavigator } from "filesystem/FSNavigator";
let dispatch = createEventDispatcher()
export let nav: FSNavigator
let { nav }: {
nav: FSNavigator;
} = $props();
// Used to detect when the file path changes
let last_path = ""
let loaded = false
let loaded = $state(false)
let player: HTMLVideoElement
let playing = false
let player: HTMLVideoElement = $state()
let playing = $state(false)
let media_session = false
let loop = false
let loop = $state(false)
export const update = async () => {
if (media_session) {
@@ -85,8 +87,7 @@ const video_keydown = (e: KeyboardEvent) => {
{#if
$nav.base.file_type === "video/x-matroska" ||
$nav.base.file_type === "video/quicktime" ||
$nav.base.file_type === "video/x-ms-asf"
}
$nav.base.file_type === "video/x-ms-asf"}
<div class="compatibility_warning">
This video file type is not compatible with every web
browser. If the video fails to play you can try downloading
@@ -96,7 +97,7 @@ const video_keydown = (e: KeyboardEvent) => {
<div class="player_and_controls">
<div class="player">
{#if loaded}
<!-- svelte-ignore a11y-media-has-caption -->
<!-- svelte-ignore a11y_media_has_caption -->
<video
bind:this={player}
controls
@@ -104,9 +105,9 @@ const video_keydown = (e: KeyboardEvent) => {
autoplay
loop={loop}
class="video"
on:pause={() => playing = false }
on:play={() => playing = true }
on:keydown={video_keydown}
onpause={() => playing = false}
onplay={() => playing = true}
onkeydown={video_keydown}
use:video_position={() => $nav.base.sha256_sum.substring(0, 8)}
>
<source src={fs_path_url($nav.base.path)} type={$nav.base.file_type} />
@@ -116,34 +117,34 @@ const video_keydown = (e: KeyboardEvent) => {
<div class="controls">
<div class="spacer"></div>
<button on:click={() => dispatch("open_sibling", -1) }>
<button onclick={() => dispatch("open_sibling", -1)}>
<i class="icon">skip_previous</i>
</button>
<button on:click={() => seek(-10)}>
<button onclick={() => seek(-10)}>
<i class="icon">replay_10</i>
</button>
<button on:click={toggle_playback} class="button_highlight">
<button onclick={toggle_playback} class="button_highlight">
{#if playing}
<i class="icon">pause</i>
{:else}
<i class="icon">play_arrow</i>
{/if}
</button>
<button on:click={() => seek(10)}>
<button onclick={() => seek(10)}>
<i class="icon">forward_10</i>
</button>
<button on:click={() => dispatch("open_sibling", 1) }>
<button onclick={() => dispatch("open_sibling", 1)}>
<i class="icon">skip_next</i>
</button>
<div style="width: 16px; height: 8px;"></div>
<button on:click={toggle_mute} class:button_red={player && player.muted}>
<button onclick={toggle_mute} class:button_red={player && player.muted}>
{#if player && player.muted}
<i class="icon">volume_off</i>
{:else}
<i class="icon">volume_up</i>
{/if}
</button>
<button on:click={toggle_fullscreen}>
<button onclick={toggle_fullscreen}>
<i class="icon">fullscreen</i>
</button>
<div class="spacer"></div>

View File

@@ -1,4 +1,4 @@
<script lang="ts" context="module">
<script lang="ts" module>
export type ZipEntry = {
size: number,
children?: {[index: string]: ZipEntry},
@@ -19,15 +19,18 @@ import { loading_finish, loading_start } from "lib/Loading";
let dispatch = createEventDispatcher()
export let nav: FSNavigator
let { nav, children }: {
nav: FSNavigator;
children?: import('svelte').Snippet;
} = $props();
let status = "loading"
let status = $state("loading")
let zip: ZipEntry = {size: 0} as ZipEntry
let zip: ZipEntry = $state({size: 0} as ZipEntry)
let uncomp_size = 0
let comp_ratio = 0
let archive_type = ""
let truncated = false
let comp_ratio = $state(0)
let archive_type = $state("")
let truncated = $state(false)
export const update = async () => {
if (nav.base.file_type === "application/x-7z-compressed") {
@@ -93,7 +96,7 @@ const recursive_size = (file: ZipEntry) => {
}
</script>
<slot></slot>
{@render children?.()}
<h1>{$nav.base.name}</h1>
@@ -110,7 +113,7 @@ const recursive_size = (file: ZipEntry) => {
{/if}
Uploaded on: {formatDate($nav.base.created, true, true, true)}
<br/>
<button class="button_highlight" on:click={() => {dispatch("download")}}>
<button class="button_highlight" onclick={() => {dispatch("download")}}>
<i class="icon">download</i>
<span>Download</span>
</button>

View File

@@ -1,8 +1,11 @@
<script lang="ts">
import ZipItem from './ZipItem.svelte';
import type { ZipEntry } from "filesystem/viewers/Zip.svelte";
import { formatDataVolume } from "util/Formatting";
export let item: ZipEntry = {} as ZipEntry
let { item = {} as ZipEntry }: {
item?: ZipEntry;
} = $props();
</script>
<!-- First get directories and render them as details collapsibles -->
@@ -23,7 +26,7 @@ export let item: ZipEntry = {} as ZipEntry
<!-- Performance optimization, only render children if details is expanded -->
{#if child.details_open}
<svelte:self item={child}></svelte:self>
<ZipItem item={child}></ZipItem>
{/if}
</details>
{/if}