Update filesystem structure
This commit is contained in:
@@ -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>
|
||||||
|
@@ -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 => {
|
||||||
|
@@ -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}
|
||||||
|
@@ -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 }
|
||||||
|
@@ -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>
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
|
||||||
|
@@ -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) }}>
|
||||||
|
@@ -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") {
|
||||||
|
Reference in New Issue
Block a user