Change filesystem navigator into a class with a svelte store implementation
This commit is contained in:
@@ -4,31 +4,44 @@ import { fs_mkdir } from "../FilesystemAPI.js";
|
||||
import Button from "../../layout/Button.svelte";
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state;
|
||||
export let nav;
|
||||
|
||||
let name_input;
|
||||
let new_dir_name = ""
|
||||
let create_dir = () => {
|
||||
let error_msg = ""
|
||||
let create_dir = async () => {
|
||||
dispatch("loading", true)
|
||||
|
||||
let form = new FormData()
|
||||
form.append("type", "dir")
|
||||
|
||||
fs_mkdir(state.base.path+"/"+new_dir_name).then(resp => {
|
||||
try {
|
||||
await fs_mkdir(nav.base.path+"/"+new_dir_name)
|
||||
new_dir_name = "" // Clear input field
|
||||
}).catch(err => {
|
||||
if (err.value && err.value === "node_already_exists") {
|
||||
alert("A directory with this name already exists")
|
||||
} else {
|
||||
alert(err)
|
||||
}
|
||||
}).finally(() => {
|
||||
error_msg = "" // Clear error msg
|
||||
dispatch("done")
|
||||
})
|
||||
} catch (err) {
|
||||
if (err.value && err.value === "node_already_exists") {
|
||||
error_msg = "A directory with this name already exists"
|
||||
} else {
|
||||
error_msg = "Server returned an error: "+err
|
||||
}
|
||||
} finally {
|
||||
dispatch("loading", false)
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => { name_input.focus() })
|
||||
onMount(() => {
|
||||
name_input.focus()
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if error_msg !== ""}
|
||||
<div class="highlight_yellow create_dir">
|
||||
{error_msg}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<form id="create_dir_form" class="create_dir" on:submit|preventDefault={create_dir}>
|
||||
<img src="/res/img/mime/folder.png" class="icon" alt="icon"/>
|
||||
<input class="dirname" type="text" bind:this={name_input} bind:value={new_dir_name} />
|
||||
|
@@ -5,7 +5,7 @@ import { fs_import } from "../FilesystemAPI";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
let file_picker
|
||||
|
||||
export const open = () => file_picker.open()
|
||||
@@ -21,7 +21,7 @@ const import_files = async files => {
|
||||
})
|
||||
|
||||
try {
|
||||
await fs_import(state.base.path, fileids)
|
||||
await fs_import(nav.base.path, fileids)
|
||||
} catch (err) {
|
||||
if (err.message) {
|
||||
alert(err.message)
|
||||
|
@@ -9,8 +9,7 @@ import FileImporter from './FileImporter.svelte';
|
||||
import { formatDate } from '../../util/Formatting.svelte';
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let fs_navigator
|
||||
export let state
|
||||
export let nav
|
||||
export let edit_window
|
||||
export let directory_view = ""
|
||||
let large_icons = false
|
||||
@@ -20,7 +19,7 @@ let creating_dir = false
|
||||
let show_hidden = false
|
||||
let file_importer
|
||||
|
||||
$: selected_files = state.children.reduce((acc, file) => {
|
||||
$: selected_files = $nav.children.reduce((acc, file) => {
|
||||
if (file.fm_selected) {
|
||||
acc++
|
||||
}
|
||||
@@ -41,13 +40,13 @@ const node_click = e => {
|
||||
// We prefix our custom state properties with fm_ to not interfere with
|
||||
// other modules
|
||||
if (mode === "viewing") {
|
||||
fs_navigator.navigate(state.children[index].path, true)
|
||||
nav.navigate(nav.children[index].path, true)
|
||||
} else if (mode === "moving") {
|
||||
// If we are moving files we can only enter directories, and only if
|
||||
// they're not selected. That last requirement prevents people from
|
||||
// moving a directory into itself
|
||||
if (state.children[index].type === "dir" && !state.children[index].fm_selected) {
|
||||
fs_navigator.navigate(state.children[index].path, true)
|
||||
if (nav.children[index].type === "dir" && !nav.children[index].fm_selected) {
|
||||
nav.navigate(nav.children[index].path, true)
|
||||
}
|
||||
} else if (mode === "selecting") {
|
||||
select_node(index)
|
||||
@@ -64,25 +63,17 @@ const node_share_click = e => {
|
||||
let index = e.detail
|
||||
|
||||
creating_dir = false
|
||||
fs_navigator.navigate(state.children[index].id, true)
|
||||
nav.navigate(nav.children[index].id, true)
|
||||
}
|
||||
const node_select = e => {
|
||||
let index = e.detail
|
||||
mode = "selecting"
|
||||
state.children[index].fm_selected = !state.children[index].fm_selected
|
||||
nav.children[index].fm_selected = !nav.children[index].fm_selected
|
||||
}
|
||||
|
||||
const node_settings = e => edit_window.edit(state.children[e.detail], false, "file")
|
||||
const node_branding = e => edit_window.edit(state.children[e.detail], false, "branding")
|
||||
const node_settings = e => edit_window.edit(nav.children[e.detail], false, "file")
|
||||
const node_branding = e => edit_window.edit(nav.children[e.detail], false, "branding")
|
||||
|
||||
const navigate_up = () => {
|
||||
creating_dir = false
|
||||
|
||||
// Go to the path of the last parent
|
||||
if (state.path.length > 1) {
|
||||
fs_navigator.navigate(state.path[state.path.length-2].path, true)
|
||||
}
|
||||
}
|
||||
const navigate_back = () => {
|
||||
creating_dir = false
|
||||
history.back()
|
||||
@@ -91,7 +82,7 @@ const navigate_back = () => {
|
||||
// Deletion function
|
||||
|
||||
const delete_selected = async () => {
|
||||
let count = state.children.reduce((acc, cur) => {
|
||||
let count = nav.children.reduce((acc, cur) => {
|
||||
if (cur.fm_selected) {
|
||||
acc++
|
||||
}
|
||||
@@ -111,7 +102,7 @@ const delete_selected = async () => {
|
||||
try {
|
||||
// Save all promises with deletion requests in an array
|
||||
let promises = []
|
||||
state.children.forEach(child => {
|
||||
nav.children.forEach(child => {
|
||||
if (!child.fm_selected) { return }
|
||||
promises.push(fs_delete_all(child.path))
|
||||
})
|
||||
@@ -123,7 +114,7 @@ const delete_selected = async () => {
|
||||
alert("Delete failed: " + err.message + " ("+err.value+")")
|
||||
} finally {
|
||||
viewing_mode()
|
||||
fs_navigator.reload()
|
||||
nav.reload()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,9 +128,9 @@ const viewing_mode = () => {
|
||||
moving_items = []
|
||||
|
||||
// Unmark all the selected files and return to viewing mode
|
||||
state.children.forEach((child, i) => {
|
||||
nav.children.forEach((child, i) => {
|
||||
if (child.fm_selected) {
|
||||
state.children[i].fm_selected = false
|
||||
nav.children[i].fm_selected = false
|
||||
}
|
||||
})
|
||||
mode = "viewing"
|
||||
@@ -181,11 +172,11 @@ const select_node = index => {
|
||||
|
||||
for (let i = id_low; i <= id_high; i++) {
|
||||
if (i != last_selected_node) {
|
||||
state.children[i].fm_selected = !state.children[i].fm_selected
|
||||
nav.children[i].fm_selected = !nav.children[i].fm_selected
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.children[index].fm_selected = !state.children[index].fm_selected
|
||||
nav.children[index].fm_selected = !nav.children[index].fm_selected
|
||||
}
|
||||
|
||||
last_selected_node = index
|
||||
@@ -194,8 +185,10 @@ const select_node = index => {
|
||||
// When the directory is reloaded we want to keep our selection, so this
|
||||
// function watches the children array for changes and updates the selection
|
||||
// when it changes
|
||||
$: update(state.children)
|
||||
$: update($nav.children)
|
||||
const update = (children) => {
|
||||
creating_dir = false
|
||||
|
||||
// Highlight the files which were previously selected
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
for (let j = 0; j < moving_items.length; j++) {
|
||||
@@ -211,7 +204,7 @@ let moving_directories = 0
|
||||
const move_start = () => {
|
||||
moving_files = 0
|
||||
moving_directories = 0
|
||||
moving_items = state.children.reduce((acc, child) => {
|
||||
moving_items = nav.children.reduce((acc, child) => {
|
||||
if (child.fm_selected) {
|
||||
if (child.type === "file") {
|
||||
moving_files++
|
||||
@@ -228,7 +221,7 @@ const move_start = () => {
|
||||
const move_here = async () => {
|
||||
dispatch("loading", true)
|
||||
|
||||
let target_dir = state.base.path + "/"
|
||||
let target_dir = nav.base.path + "/"
|
||||
|
||||
try {
|
||||
let promises = []
|
||||
@@ -244,7 +237,7 @@ const move_here = async () => {
|
||||
alert("Move failed: " + err.message + " ("+err.value+")")
|
||||
} finally {
|
||||
viewing_mode()
|
||||
fs_navigator.reload()
|
||||
nav.reload()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,10 +261,10 @@ onMount(() => {
|
||||
<button on:click={navigate_back} title="Back">
|
||||
<i class="icon">arrow_back</i>
|
||||
</button>
|
||||
<button on:click={navigate_up} disabled={state.path.length <= 1} title="Up">
|
||||
<button on:click={() => nav.navigate_up()} disabled={$nav.path.length <= 1} title="Up">
|
||||
<i class="icon">north</i>
|
||||
</button>
|
||||
<button on:click={fs_navigator.reload()} title="Refresh directory listing">
|
||||
<button on:click={() => nav.reload()} title="Refresh directory listing">
|
||||
<i class="icon">refresh</i>
|
||||
</button>
|
||||
|
||||
@@ -300,7 +293,7 @@ onMount(() => {
|
||||
</button>
|
||||
|
||||
<div class="toolbar_spacer"></div>
|
||||
{#if state.permissions.update}
|
||||
{#if $nav.permissions.update}
|
||||
<button on:click={() => dispatch("upload_picker")} title="Upload files to this directory">
|
||||
<i class="icon">cloud_upload</i>
|
||||
</button>
|
||||
@@ -335,7 +328,7 @@ onMount(() => {
|
||||
{:else if mode === "moving"}
|
||||
<div class="toolbar toolbar_edit">
|
||||
<Button click={viewing_mode} icon="close"/>
|
||||
<Button click={navigate_up} disabled={state.path.length <= 1} icon="north"/>
|
||||
<Button click={() => nav.navigate_up()} disabled={$nav.path.length <= 1} icon="north"/>
|
||||
<div class="toolbar_spacer">
|
||||
Moving {moving_files} files and {moving_directories} directories
|
||||
</div>
|
||||
@@ -345,14 +338,10 @@ onMount(() => {
|
||||
{/if}
|
||||
|
||||
{#if creating_dir}
|
||||
<CreateDirectory
|
||||
state={state}
|
||||
on:done={() => {fs_navigator.reload(); creating_dir = false;}}
|
||||
on:loading
|
||||
/>
|
||||
<CreateDirectory nav={nav} on:done={() => nav.reload()} on:loading />
|
||||
{/if}
|
||||
|
||||
{#if state.base.path === "/me"}
|
||||
{#if $nav.base.path === "/me"}
|
||||
<div class="highlight_shaded" style="background-color: rgba(255, 255, 0, 0.05); border-radius: 0;">
|
||||
The filesystem is experimental!
|
||||
<a href="/filesystem">Please read the guide</a>
|
||||
@@ -361,12 +350,12 @@ onMount(() => {
|
||||
</div>
|
||||
|
||||
|
||||
{#if state.base.abuse_type !== undefined}
|
||||
{#if $nav.base.abuse_type !== undefined}
|
||||
<div class="highlight_red">
|
||||
This directory has received an abuse report. It cannot be
|
||||
shared.<br/>
|
||||
Type of abuse: {state.base.abuse_type}<br/>
|
||||
Report time: {formatDate(state.base.abuse_report_time, true, true, true)}
|
||||
Type of abuse: {$nav.base.abuse_type}<br/>
|
||||
Report time: {formatDate($nav.base.abuse_report_time, true, true, true)}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -374,7 +363,7 @@ onMount(() => {
|
||||
|
||||
{#if directory_view === "list"}
|
||||
<ListView
|
||||
state={state}
|
||||
nav={nav}
|
||||
show_hidden={show_hidden}
|
||||
large_icons={large_icons}
|
||||
on:node_click={node_click}
|
||||
@@ -386,7 +375,7 @@ onMount(() => {
|
||||
/>
|
||||
{:else if directory_view === "gallery"}
|
||||
<GalleryView
|
||||
state={state}
|
||||
nav={nav}
|
||||
show_hidden={show_hidden}
|
||||
large_icons={large_icons}
|
||||
on:node_click={node_click}
|
||||
@@ -398,10 +387,10 @@ onMount(() => {
|
||||
</div>
|
||||
|
||||
<FileImporter
|
||||
state={state}
|
||||
nav={nav}
|
||||
bind:this={file_importer}
|
||||
on:loading
|
||||
on:reload={() => fs_navigator.reload()}
|
||||
on:reload={() => nav.reload()}
|
||||
/>
|
||||
|
||||
<style>
|
||||
|
@@ -3,12 +3,11 @@ import { createEventDispatcher, onMount } from 'svelte'
|
||||
import ListView from './ListView.svelte'
|
||||
import GalleryView from './GalleryView.svelte'
|
||||
import Modal from '../../util/Modal.svelte';
|
||||
import Navigator from '../Navigator.svelte';
|
||||
import LoadingIndicator from '../../util/LoadingIndicator.svelte';
|
||||
import Breadcrumbs from '../Breadcrumbs.svelte'
|
||||
import { Navigator } from '../Navigator';
|
||||
|
||||
let fs_navigator
|
||||
let state
|
||||
let nav = new Navigator(false)
|
||||
let modal
|
||||
let dispatch = createEventDispatcher()
|
||||
let directory_view = ""
|
||||
@@ -20,10 +19,10 @@ export let select_multiple = false
|
||||
|
||||
export const open = path => {
|
||||
modal.show()
|
||||
fs_navigator.navigate(path, false)
|
||||
nav.navigate(path, false)
|
||||
}
|
||||
|
||||
$: selected_files = state && state.children.reduce((acc, file) => {
|
||||
$: selected_files = $nav.children.reduce((acc, file) => {
|
||||
if (file.fm_selected) {
|
||||
acc++
|
||||
}
|
||||
@@ -35,8 +34,8 @@ $: selected_files = state && state.children.reduce((acc, file) => {
|
||||
const node_click = e => {
|
||||
let index = e.detail
|
||||
|
||||
if (state.children[index].type === "dir") {
|
||||
fs_navigator.navigate(state.children[index].path, true)
|
||||
if (nav.children[index].type === "dir") {
|
||||
nav.navigate(nav.children[index].path, true)
|
||||
} else {
|
||||
select_node(index)
|
||||
}
|
||||
@@ -51,13 +50,7 @@ let node_context = e => {
|
||||
const node_select = e => {
|
||||
let index = e.detail
|
||||
mode = "selecting"
|
||||
state.children[index].fm_selected = !state.children[index].fm_selected
|
||||
}
|
||||
const navigate_up = () => {
|
||||
// Go to the path of the last parent
|
||||
if (state.path.length > 1) {
|
||||
fs_navigator.navigate(state.path[state.path.length-2].path, true)
|
||||
}
|
||||
nav.children[index].fm_selected = !nav.children[index].fm_selected
|
||||
}
|
||||
const toggle_view = () => {
|
||||
if (directory_view === "list") {
|
||||
@@ -87,17 +80,17 @@ const select_node = index => {
|
||||
|
||||
for (let i = id_low; i <= id_high; i++) {
|
||||
if (i != last_selected_node) {
|
||||
state.children[i].fm_selected = !state.children[i].fm_selected
|
||||
nav.children[i].fm_selected = !nav.children[i].fm_selected
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Deselect all other entries first
|
||||
if (!select_multiple) {
|
||||
for (let i = 0; i < state.children.length; i++) {
|
||||
state.children[i].fm_selected = false
|
||||
for (let i = 0; i < nav.children.length; i++) {
|
||||
nav.children[i].fm_selected = false
|
||||
}
|
||||
}
|
||||
state.children[index].fm_selected = !state.children[index].fm_selected
|
||||
nav.children[index].fm_selected = !nav.children[index].fm_selected
|
||||
}
|
||||
|
||||
last_selected_node = index
|
||||
@@ -105,9 +98,9 @@ const select_node = index => {
|
||||
|
||||
let done = () => {
|
||||
let selected_files = []
|
||||
for (let i = 0; i < state.children.length; i++) {
|
||||
if (state.children[i].fm_selected) {
|
||||
selected_files.push(state.children[i])
|
||||
for (let i = 0; i < nav.children.length; i++) {
|
||||
if (nav.children[i].fm_selected) {
|
||||
selected_files.push(nav.children[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,22 +123,15 @@ onMount(() => {
|
||||
|
||||
<svelte:window on:keydown={detect_shift} on:keyup={detect_shift} />
|
||||
|
||||
<Navigator
|
||||
history_enabled={false}
|
||||
bind:this={fs_navigator}
|
||||
bind:state
|
||||
on:loading={loading_evt}
|
||||
/>
|
||||
|
||||
<Modal bind:this={modal} width="900px">
|
||||
<div class="header" slot="title">
|
||||
<button class="button round" on:click={modal.hide}>
|
||||
<i class="icon">close</i>
|
||||
</button>
|
||||
<button on:click={navigate_up} disabled={state.path.length <= 1} title="Up">
|
||||
<button on:click={() => nav.navigate_up()} disabled={$nav.path.length <= 1} title="Up">
|
||||
<i class="icon">north</i>
|
||||
</button>
|
||||
<button on:click={fs_navigator.reload()} title="Refresh directory listing">
|
||||
<button on:click={() => nav.reload()} title="Refresh directory listing">
|
||||
<i class="icon">refresh</i>
|
||||
</button>
|
||||
|
||||
@@ -174,20 +160,22 @@ onMount(() => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Breadcrumbs state={state} fs_navigator={fs_navigator}/>
|
||||
<Breadcrumbs nav={nav}/>
|
||||
|
||||
{#if directory_view === "list"}
|
||||
<ListView
|
||||
state={state}
|
||||
nav={nav}
|
||||
show_hidden={show_hidden}
|
||||
large_icons={large_icons}
|
||||
hide_edit
|
||||
hide_branding
|
||||
on:node_click={node_click}
|
||||
on:node_context={node_context}
|
||||
on:node_select={node_select}
|
||||
/>
|
||||
{:else if directory_view === "gallery"}
|
||||
<GalleryView
|
||||
state={state}
|
||||
nav={nav}
|
||||
show_hidden={show_hidden}
|
||||
large_icons={large_icons}
|
||||
on:node_click={node_click}
|
||||
|
@@ -3,13 +3,13 @@ import { createEventDispatcher } from "svelte"
|
||||
import { fs_encode_path, fs_node_icon, fs_node_type } from "../FilesystemUtil";
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
export let show_hidden = false
|
||||
export let large_icons = false
|
||||
</script>
|
||||
|
||||
<div class="gallery">
|
||||
{#each state.children as child, index (child.path)}
|
||||
{#each $nav.children as child, index (child.path)}
|
||||
<a class="file"
|
||||
href={"/d"+fs_encode_path(child.path)}
|
||||
on:click|preventDefault={() => dispatch("node_click", index)}
|
||||
|
@@ -5,7 +5,7 @@ import { fs_encode_path, fs_node_icon } from "../FilesystemUtil";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
export let nav
|
||||
export let show_hidden = false
|
||||
export let large_icons = false
|
||||
export let hide_edit = false
|
||||
@@ -19,7 +19,7 @@ export let hide_branding = false
|
||||
<td>Size</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{#each state.children as child, index (child.path)}
|
||||
{#each $nav.children as child, index (child.path)}
|
||||
<a
|
||||
href={"/d"+fs_encode_path(child.path)}
|
||||
on:click|preventDefault={() => dispatch("node_click", index)}
|
||||
@@ -57,7 +57,7 @@ export let hide_branding = false
|
||||
<i class="icon">palette</i>
|
||||
</button>
|
||||
{/if}
|
||||
{#if state.permissions.update && !hide_edit}
|
||||
{#if $nav.permissions.update && !hide_edit}
|
||||
<button class="action_button" on:click|preventDefault|stopPropagation={() => dispatch("node_settings", index)}>
|
||||
<i class="icon">edit</i>
|
||||
</button>
|
||||
|
Reference in New Issue
Block a user