Update filesystem structure

This commit is contained in:
2023-04-11 23:44:50 +02:00
parent 9b451b37ea
commit 971a0fe539
8 changed files with 58 additions and 48 deletions

View File

@@ -12,10 +12,6 @@ import PDF from './viewers/PDF.svelte';
import PixeldrainLogo from '../util/PixeldrainLogo.svelte'; import PixeldrainLogo from '../util/PixeldrainLogo.svelte';
import LoadingIndicator from '../util/LoadingIndicator.svelte'; import LoadingIndicator from '../util/LoadingIndicator.svelte';
// Elements
let file_viewer
let header_bar
let toolbar_visible = (window.innerWidth > 600) let toolbar_visible = (window.innerWidth > 600)
let toolbar_toggle = () => { let toolbar_toggle = () => {
toolbar_visible = !toolbar_visible toolbar_visible = !toolbar_visible
@@ -38,10 +34,17 @@ let download_frame
// State // State
let state = { let state = {
bucket: window.initial_node.bucket, path: window.initial_node.path,
parents: window.initial_node.parents, base: window.initial_node.path[window.initial_node.base_index],
base: window.initial_node.base, base_index: window.initial_node.base_index,
root: window.initial_node.path[0],
children: window.initial_node.children, children: window.initial_node.children,
permissions: {
create: window.initial_node.permissions.create,
read: window.initial_node.permissions.read,
update: window.initial_node.permissions.update,
delete: window.initial_node.permissions.delete,
},
// Passwords for accessing this bucket. Passwords are not always required // Passwords for accessing this bucket. Passwords are not always required
// but sometimes they are // but sometimes they are
@@ -59,7 +62,7 @@ let state = {
// Root path of the bucket. Used for navigation by prepending it to a file // Root path of the bucket. Used for navigation by prepending it to a file
// path // path
path_root: "/d/"+window.initial_node.bucket.id, path_root: "/d/"+window.initial_node.path[0].id,
loading: true, loading: true,
viewer_type: "", viewer_type: "",
shuffle: false, shuffle: false,
@@ -83,11 +86,13 @@ const sort_children = children => {
const navigate = (path, pushHist) => { const navigate = (path, pushHist) => {
state.loading = true state.loading = true
fs_get_node(state.bucket.id, path).then(resp => { fs_get_node(state.root.id, path).then(resp => {
window.document.title = resp.base.name+" ~ pixeldrain" window.document.title = resp.path[resp.base_index].name+" ~ pixeldrain"
if (pushHist) { if (pushHist) {
window.history.pushState( window.history.pushState(
{}, window.document.title, "/d/"+resp.bucket.id+resp.base.path, {},
window.document.title,
"/d/"+resp.path[0].id+resp.path[resp.base_index].path,
) )
} }
@@ -103,10 +108,10 @@ const navigate = (path, pushHist) => {
const open_node = (node) => { const open_node = (node) => {
// If the new node is a child of the previous node we save the parent's // If the new node is a child of the previous node we save the parent's
// children array // children array
if (node.parents.length > 0 && node.parents[node.parents.length-1].path === state.base.path) { if (node.path.length > 0 && node.path[node.path.length-1].path === state.base.path) {
console.debug("Current parent path and new node path match. Saving siblings") console.debug("Current parent path and new node path match. Saving siblings")
state.siblings_path = node.parents[node.parents.length-1].path state.siblings_path = node.path[node.path.length-1].path
state.siblings = state.children state.siblings = state.children
} }
@@ -114,10 +119,12 @@ const open_node = (node) => {
sort_children(node.children) sort_children(node.children)
// Update shared state // Update shared state
state.bucket = node.bucket state.path = node.path
state.parents = node.parents state.base = node.path[node.base_index]
state.base = node.base state.base_index = node.base_index
state.root = node.path[0]
state.children = node.children state.children = node.children
state.permissions = node.permissions
// Update the viewer area with the right viewer type // Update the viewer area with the right viewer type
if (state.base.type === "bucket" || state.base.type === "dir") { if (state.base.type === "bucket" || state.base.type === "dir") {
@@ -154,26 +161,26 @@ onMount(() => open_node(window.initial_node))
// file which is currently open. Give a positive number to move forward and a // file which is currently open. Give a positive number to move forward and a
// negative number to move backward // negative number to move backward
const open_sibling = async offset => { const open_sibling = async offset => {
if (state.parents.length == 0) { if (state.path.length <= 1) {
return return
} }
state.loading = true state.loading = true
// Check if we already have siblings cached // Check if we already have siblings cached
if (state.siblings != null && state.siblings_path == state.parents[state.parents.length - 1].path) { if (state.siblings != null && state.siblings_path == state.path[state.path.length - 2].path) {
console.debug("Using cached siblings") console.debug("Using cached siblings")
} else { } else {
console.debug("Cached siblings not available. Fetching new") console.debug("Cached siblings not available. Fetching new")
try { try {
let resp = await fs_get_node(state.bucket.id, state.parents[state.parents.length - 1].path) let resp = await fs_get_node(state.root.id, state.path[state.path.length - 2].path)
// Sort directory children to make sure the order is consistent // Sort directory children to make sure the order is consistent
sort_children(resp.base.children) sort_children(resp.children)
// Save new siblings in global state // Save new siblings in global state
state.siblings_path = state.parents[state.parents.length - 1].path state.siblings_path = state.path[state.path.length - 2].path
state.siblings = resp.base.children state.siblings = resp.children
} catch (err) { } catch (err) {
console.error(err) console.error(err)
alert(err) alert(err)
@@ -225,7 +232,7 @@ const open_sibling = async offset => {
window.onpopstate = (e) => { window.onpopstate = (e) => {
if(e.state){ if(e.state){
// Get the part of the URL after the bucket ID and navigate to it // Get the part of the URL after the bucket ID and navigate to it
let locsplit = document.location.pathname.split(state.bucket.id+"/", 2) let locsplit = document.location.pathname.split(state.root.id+"/", 2)
navigate(decodeURIComponent(locsplit[1])) navigate(decodeURIComponent(locsplit[1]))
} }
}; };
@@ -261,7 +268,7 @@ const keydown = e => {
}; };
const download = () => { const download = () => {
download_frame.src = fs_get_file_url(state.bucket.id, state.base.path) + "?attach" download_frame.src = fs_get_file_url(state.root.id, state.base.path) + "?attach"
} }
const share = () => { const share = () => {
@@ -273,8 +280,8 @@ const share = () => {
<LoadingIndicator loading={state.loading}/> <LoadingIndicator loading={state.loading}/>
<div bind:this={file_viewer} class="file_viewer"> <div class="file_viewer">
<div bind:this={header_bar} class="file_viewer_headerbar"> <div class="file_viewer_headerbar">
<button on:click={toolbar_toggle} class="button_toggle_toolbar round" class:button_highlight={toolbar_visible}> <button on:click={toolbar_toggle} class="button_toggle_toolbar round" class:button_highlight={toolbar_visible}>
<i class="icon">menu</i> <i class="icon">menu</i>
</button> </button>
@@ -282,15 +289,18 @@ const share = () => {
<PixeldrainLogo style="height: 1.6em; width: 1.6em; margin: 0 0.2em 0 0; color: currentColor;"></PixeldrainLogo> <PixeldrainLogo style="height: 1.6em; width: 1.6em; margin: 0 0.2em 0 0; color: currentColor;"></PixeldrainLogo>
</a> </a>
<div class="file_viewer_headerbar_title"> <div class="file_viewer_headerbar_title">
{#each state.parents as parent} {#each state.path as node, i}
<a <a
href={state.path_root+parent.path} href={state.path_root+node.path}
class="breadcrumb button" class="breadcrumb button"
on:click|preventDefault={() => {navigate(parent.path, true)}}> class:button_highlight={state.base_index === i}
{parent.name} on:click|preventDefault={() => {navigate(node.path, true)}}>
</a> / {node.name}
</a>
{#if i < state.base_index}
/
{/if}
{/each} {/each}
<div class="breadcrumb button button_highlight">{state.base.name}</div>
</div> </div>
</div> </div>
<div class="list_navigator"></div> <div class="list_navigator"></div>
@@ -377,10 +387,10 @@ const share = () => {
<tr><td>SHA256 sum</td><td>{state.base.sha256_sum}</td></tr> <tr><td>SHA256 sum</td><td>{state.base.sha256_sum}</td></tr>
{/if} {/if}
<tr><td colspan="2"><h3>Bucket details</h3></td></tr> <tr><td colspan="2"><h3>Bucket details</h3></td></tr>
<tr><td>ID</td><td>{state.bucket.id}</td></tr> <tr><td>ID</td><td>{state.root.id}</td></tr>
<tr><td>Name</td><td>{state.bucket.name}</td></tr> <tr><td>Name</td><td>{state.root.name}</td></tr>
<tr><td>Date created</td><td>{formatDate(state.bucket.date_created, true, true, true)}</td></tr> <tr><td>Date created</td><td>{formatDate(state.root.date_created, true, true, true)}</td></tr>
<tr><td>Date modified</td><td>{formatDate(state.bucket.date_modified, true, true, true)}</td></tr> <tr><td>Date modified</td><td>{formatDate(state.root.date_modified, true, true, true)}</td></tr>
</table> </table>
</Modal> </Modal>
</div> </div>

View File

@@ -13,7 +13,7 @@ let create_dir = () => {
form.append("type", "dir") form.append("type", "dir")
fs_create_directory( fs_create_directory(
state.bucket.id, state.base.path, create_dir_name, state.root.id, state.base.path, create_dir_name,
).then(resp => { ).then(resp => {
create_dir_name = "" // Clear input field create_dir_name = "" // Clear input field
}).catch(err => { }).catch(err => {

View File

@@ -34,8 +34,8 @@ const navigate_up = () => {
creating_dir = false creating_dir = false
// Go to the path of the last parent // Go to the path of the last parent
if (state.parents.length !== 0) { if (state.path.length > 1) {
dispatch("navigate", state.parents[state.parents.length-1].path) dispatch("navigate", state.path[state.path.length-2].path)
} }
} }
const reload = () => { dispatch("navigate", state.base.path) } const reload = () => { dispatch("navigate", state.base.path) }
@@ -66,7 +66,7 @@ const delete_selected = () => {
let promises = [] let promises = []
state.children.forEach(child => { state.children.forEach(child => {
if (!child.fm_selected) { return } if (!child.fm_selected) { return }
promises.push(fs_delete_node(state.bucket.id, child.path)) promises.push(fs_delete_node(state.root.id, child.path))
}) })
// Wait for all the promises to finish // Wait for all the promises to finish
@@ -96,7 +96,7 @@ const toggle_select = () => {
<div class="container"> <div class="container">
<div class="width_container"> <div class="width_container">
<div class="toolbar"> <div class="toolbar">
<button on:click={navigate_up} disabled={state.parents.length === 0} title="Back"> <button on:click={navigate_up} disabled={state.path.length <= 1} title="Back">
<i class="icon">arrow_back</i> <i class="icon">arrow_back</i>
</button> </button>
<button on:click={reload} title="Refresh directory listing"> <button on:click={reload} title="Refresh directory listing">
@@ -113,7 +113,7 @@ const toggle_select = () => {
{/if} {/if}
<div class="toolbar_spacer"></div> <div class="toolbar_spacer"></div>
{#if state.bucket.permissions.update} {#if state.permissions.update}
<button on:click={uploader.picker} title="Upload files to this directory"> <button on:click={uploader.picker} title="Upload files to this directory">
<i class="icon">cloud_upload</i> <i class="icon">cloud_upload</i>
</button> </button>
@@ -157,7 +157,7 @@ const toggle_select = () => {
<FileUploader <FileUploader
bind:this={uploader} bind:this={uploader}
bucket_id={state.bucket.id} bucket_id={state.root.id}
target_dir={state.base.path} target_dir={state.base.path}
on:reload={reload} on:reload={reload}
write_password={state.write_password} write_password={state.write_password}

View File

@@ -53,7 +53,7 @@ onMount(() => {
<audio <audio
bind:this={player} bind:this={player}
class="player" class="player"
src={fs_get_file_url(state.bucket.id, state.base.path)} src={fs_get_file_url(state.root.id, state.base.path)}
autoplay="autoplay" autoplay="autoplay"
controls="controls" controls="controls"
on:pause={() => playing = false } on:pause={() => playing = false }

View File

@@ -51,7 +51,7 @@ const mouseup = (e) => {
on:doubletap={() => {zoom = !zoom}} on:doubletap={() => {zoom = !zoom}}
on:mousedown={mousedown} on:mousedown={mousedown}
class="image" class:zoom class="image" class:zoom
src={fs_get_file_url(state.bucket.id, state.base.path)} src={fs_get_file_url(state.root.id, state.base.path)}
alt="no description available" /> alt="no description available" />
</div> </div>

View File

@@ -5,7 +5,7 @@ export let state
<iframe <iframe
class="container" class="container"
src={"/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(fs_get_file_url(state.bucket.id, state.base.path))} src={"/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(fs_get_file_url(state.root.id, state.base.path))}
title="PDF viewer"> title="PDF viewer">
</iframe> </iframe>

View File

@@ -38,7 +38,7 @@ onMount(() => {
<video <video
bind:this={player} bind:this={player}
class="player" class="player"
src={fs_get_file_url(state.bucket.id, state.base.path)} src={fs_get_file_url(state.root.id, state.base.path)}
autoplay="autoplay" autoplay="autoplay"
controls="controls" controls="controls"
on:ended={() => { dispatch("open_sibling", 1) }}> on:ended={() => { dispatch("open_sibling", 1) }}>

View File

@@ -30,7 +30,7 @@ func (wc *WebController) serveDirectory(w http.ResponseWriter, r *http.Request,
return return
} }
td.Title = fmt.Sprintf("%s ~ pixeldrain", node.Base.Name) td.Title = fmt.Sprintf("%s ~ pixeldrain", node.Path[node.BaseIndex].Name)
td.Other = node td.Other = node
err = wc.templates.Get().ExecuteTemplate(w, "filesystem", td) err = wc.templates.Get().ExecuteTemplate(w, "filesystem", td)
if err != nil && !strings.Contains(err.Error(), "broken pipe") { if err != nil && !strings.Contains(err.Error(), "broken pipe") {