Remove the need to provide a bucket ID to each API call
This commit is contained in:
@@ -19,7 +19,7 @@ const visibility_change = visible => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: direct_url = window.location.origin+fs_path_url(state.root.id, state.base.path)
|
$: direct_url = window.location.origin+fs_path_url(state.base.path)
|
||||||
$: share_url = generate_share_url(state.path)
|
$: share_url = generate_share_url(state.path)
|
||||||
|
|
||||||
let chart
|
let chart
|
||||||
@@ -75,7 +75,7 @@ let update_chart = async (base, timespan, interval) => {
|
|||||||
let end = new Date()
|
let end = new Date()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let resp = await fs_timeseries(state.root.id, base.path, start, end, interval)
|
let resp = await fs_timeseries(base.path, start, end, interval)
|
||||||
|
|
||||||
chart.data().datasets = [
|
chart.data().datasets = [
|
||||||
{
|
{
|
||||||
|
@@ -5,7 +5,6 @@ import { createEventDispatcher } from "svelte";
|
|||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let bucket = ""
|
|
||||||
export let fs_navigator
|
export let fs_navigator
|
||||||
let file = {
|
let file = {
|
||||||
path: "",
|
path: "",
|
||||||
@@ -42,7 +41,6 @@ const save = async () => {
|
|||||||
try {
|
try {
|
||||||
dispatch("loading", true)
|
dispatch("loading", true)
|
||||||
await fs_update(
|
await fs_update(
|
||||||
bucket,
|
|
||||||
file.path,
|
file.path,
|
||||||
{
|
{
|
||||||
shared: shared,
|
shared: shared,
|
||||||
@@ -55,12 +53,16 @@ const save = async () => {
|
|||||||
let parent = file.path.slice(0, -file.name.length)
|
let parent = file.path.slice(0, -file.name.length)
|
||||||
console.log("Moving", file.path, "to", parent+file_name)
|
console.log("Moving", file.path, "to", parent+file_name)
|
||||||
|
|
||||||
await fs_rename(bucket, file.path, parent+file_name)
|
await fs_rename(file.path, parent+file_name)
|
||||||
file.path = parent+file_name
|
file.path = parent+file_name
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
if (err.message) {
|
||||||
|
alert(err.message)
|
||||||
|
} else {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
alert(err)
|
alert(err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} finally {
|
} finally {
|
||||||
dispatch("loading", false)
|
dispatch("loading", false)
|
||||||
|
@@ -26,7 +26,7 @@ const update_base = async base => {
|
|||||||
error_msg = "Loading..."
|
error_msg = "Loading..."
|
||||||
|
|
||||||
let ws_endpoint = location.origin.replace(/^http/, 'ws') +
|
let ws_endpoint = location.origin.replace(/^http/, 'ws') +
|
||||||
fs_path_url(state.root.id, base.path).replace(/^http/, 'ws') +
|
fs_path_url(base.path).replace(/^http/, 'ws') +
|
||||||
"?download_stats"
|
"?download_stats"
|
||||||
|
|
||||||
console.log("Opening socket to", ws_endpoint)
|
console.log("Opening socket to", ws_endpoint)
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount, tick } from 'svelte';
|
import { onMount } from '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';
|
||||||
import EditWindow from './EditWindow.svelte';
|
import EditWindow from './EditWindow.svelte';
|
||||||
import { fs_file_url } from './FilesystemUtil';
|
|
||||||
import Toolbar from './Toolbar.svelte';
|
import Toolbar from './Toolbar.svelte';
|
||||||
import Breadcrumbs from './Breadcrumbs.svelte';
|
import Breadcrumbs from './Breadcrumbs.svelte';
|
||||||
import DetailsWindow from './DetailsWindow.svelte';
|
import DetailsWindow from './DetailsWindow.svelte';
|
||||||
@@ -30,7 +29,6 @@ let state = {
|
|||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
base: window.initial_node.path[window.initial_node.base_index],
|
base: window.initial_node.path[window.initial_node.base_index],
|
||||||
root: window.initial_node.path[0],
|
|
||||||
|
|
||||||
// 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
|
||||||
@@ -90,7 +88,7 @@ const keydown = e => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const download = () => {
|
const download = () => {
|
||||||
download_frame.src = fs_file_url(state.root.id, state.base.path) + "?attach"
|
download_frame.src = fs_path_url(state.base.path) + "?attach"
|
||||||
}
|
}
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
@@ -187,7 +185,6 @@ const loading_evt = e => {
|
|||||||
<EditWindow
|
<EditWindow
|
||||||
bind:this={edit_window}
|
bind:this={edit_window}
|
||||||
bind:visible={edit_visible}
|
bind:visible={edit_visible}
|
||||||
bucket={state.root.id}
|
|
||||||
fs_navigator={fs_navigator}
|
fs_navigator={fs_navigator}
|
||||||
on:loading={loading_evt}
|
on:loading={loading_evt}
|
||||||
/>
|
/>
|
||||||
|
@@ -14,7 +14,7 @@ export const fs_check_response = async resp => {
|
|||||||
return JSON.parse(text)
|
return JSON.parse(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_mkdir = async (bucket, path, opts = null) => {
|
export const fs_mkdir = async (path, opts = null) => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("action", "mkdir")
|
form.append("action", "mkdir")
|
||||||
|
|
||||||
@@ -23,11 +23,11 @@ export const fs_mkdir = async (bucket, path, opts = null) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, path), { method: "POST", body: form })
|
await fetch(fs_path_url(path), { method: "POST", body: form })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_mkdirall = async (bucket, path, opts = null) => {
|
export const fs_mkdirall = async (path, opts = null) => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("action", "mkdirall")
|
form.append("action", "mkdirall")
|
||||||
|
|
||||||
@@ -36,13 +36,13 @@ export const fs_mkdirall = async (bucket, path, opts = null) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, path), { method: "POST", body: form })
|
await fetch(fs_path_url(path), { method: "POST", body: form })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_get_node = async (bucket, path) => {
|
export const fs_get_node = async path => {
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, path) + "?stat")
|
await fetch(fs_path_url(path) + "?stat")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ export const fs_get_node = async (bucket, path) => {
|
|||||||
// - shared, boolean. If true the node will receive a public ID
|
// - shared, boolean. If true the node will receive a public ID
|
||||||
//
|
//
|
||||||
// Returns the modified filesystem node object
|
// Returns the modified filesystem node object
|
||||||
export const fs_update = async (bucket, path, opts) => {
|
export const fs_update = async (path, opts) => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("action", "update")
|
form.append("action", "update")
|
||||||
|
|
||||||
@@ -77,45 +77,45 @@ export const fs_update = async (bucket, path, opts) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, path), { method: "POST", body: form })
|
await fetch(fs_path_url(path), { method: "POST", body: form })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_rename = async (bucket, old_path, new_path) => {
|
export const fs_rename = async (old_path, new_path) => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("action", "rename")
|
form.append("action", "rename")
|
||||||
form.append("target", new_path)
|
form.append("target", new_path)
|
||||||
|
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, old_path), { method: "POST", body: form })
|
await fetch(fs_path_url(old_path), { method: "POST", body: form })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_delete = async (bucket, path) => {
|
export const fs_delete = async path => {
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, path), { method: "DELETE" })
|
await fetch(fs_path_url(path), { method: "DELETE" })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export const fs_delete_all = async (bucket, path) => {
|
export const fs_delete_all = async path => {
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(fs_path_url(bucket, path) + "?recursive", { method: "DELETE" })
|
await fetch(fs_path_url(path) + "?recursive", { method: "DELETE" })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_search = async (bucket, path, term, limit = 10) => {
|
export const fs_search = async (path, term, limit = 10) => {
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(
|
await fetch(
|
||||||
fs_path_url(bucket, path) +
|
fs_path_url(path) +
|
||||||
"?search=" + encodeURIComponent(term) +
|
"?search=" + encodeURIComponent(term) +
|
||||||
"&limit=" + limit
|
"&limit=" + limit
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_timeseries = async (bucket, path, start, end, interval = 60) => {
|
export const fs_timeseries = async (path, start, end, interval = 60) => {
|
||||||
return await fs_check_response(
|
return await fs_check_response(
|
||||||
await fetch(
|
await fetch(
|
||||||
fs_path_url(bucket, path) +
|
fs_path_url(path) +
|
||||||
"?timeseries" +
|
"?timeseries" +
|
||||||
"&start=" + start.toISOString() +
|
"&start=" + start.toISOString() +
|
||||||
"&end=" + end.toISOString() +
|
"&end=" + end.toISOString() +
|
||||||
|
@@ -1,23 +1,23 @@
|
|||||||
export const fs_split_path = (path) => {
|
export const fs_split_path = path => {
|
||||||
let patharr = path.split("/")
|
let patharr = path.split("/")
|
||||||
return { base: patharr.pop(), parent: patharr.join("/") }
|
return { base: patharr.pop(), parent: patharr.join("/") }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_path_url = (bucket, path) => {
|
export const fs_encode_path = path => {
|
||||||
// Encode all path elements separately to preserve forward slashes
|
// Encode all path elements separately to preserve forward slashes
|
||||||
let split = path.split("/")
|
let split = path.split("/")
|
||||||
for (let i = 0; i < split.length; i++) {
|
for (let i = 0; i < split.length; i++) {
|
||||||
split[i] = encodeURIComponent(split[i])
|
split[i] = encodeURIComponent(split[i])
|
||||||
}
|
}
|
||||||
return window.api_endpoint + "/filesystem/" + bucket + split.join("/")
|
return split.join("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_file_url = (bucket, path) => {
|
export const fs_path_url = path => {
|
||||||
return fs_path_url(bucket, path)
|
return window.api_endpoint + "/filesystem" + fs_encode_path(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_thumbnail_url = (bucket, path, width = 64, height = 64) => {
|
export const fs_thumbnail_url = (path, width = 64, height = 64) => {
|
||||||
return fs_path_url(bucket, path) + "?thumbnail&width=" + width + "&height=" + height
|
return fs_path_url(path) + "?thumbnail&width=" + width + "&height=" + height
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_node_type = node => {
|
export const fs_node_type = node => {
|
||||||
@@ -55,7 +55,7 @@ export const fs_node_type = node => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs_node_icon = (bucket, node, width = 64, height = 64) => {
|
export const fs_node_icon = (node, width = 64, height = 64) => {
|
||||||
if (node.type === "dir") {
|
if (node.type === "dir") {
|
||||||
// Folders with an ID are publically shared, use the shared folder icon
|
// Folders with an ID are publically shared, use the shared folder icon
|
||||||
if (node.id) {
|
if (node.id) {
|
||||||
@@ -65,5 +65,5 @@ export const fs_node_icon = (bucket, node, width = 64, height = 64) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fs_thumbnail_url(bucket, node.path, width, height)
|
return fs_thumbnail_url(node.path, width, height)
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import { fs_get_node } from "./FilesystemAPI";
|
import { fs_get_node } from "./FilesystemAPI";
|
||||||
import { fs_split_path } from "./FilesystemUtil";
|
import { fs_encode_path, fs_split_path } from "./FilesystemUtil";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@@ -15,9 +15,6 @@ export let state = {
|
|||||||
// The part of the path that base_index points to
|
// The part of the path that base_index points to
|
||||||
base: {},
|
base: {},
|
||||||
|
|
||||||
// First node in the path
|
|
||||||
root: {},
|
|
||||||
|
|
||||||
// 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
|
||||||
read_password: "",
|
read_password: "",
|
||||||
@@ -30,15 +27,19 @@ export let state = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const navigate = async (path, push_history) => {
|
export const navigate = async (path, push_history) => {
|
||||||
|
if (path[0] !== "/") {
|
||||||
|
path = "/"+path
|
||||||
|
}
|
||||||
|
|
||||||
dispatch("loading", true)
|
dispatch("loading", true)
|
||||||
console.debug("Navigating to path", path, push_history)
|
console.debug("Navigating to path", path, push_history)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let resp = await fs_get_node(state.root.id, path)
|
let resp = await fs_get_node(path)
|
||||||
open_node(resp, push_history)
|
open_node(resp, push_history)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.value && err.value === "path_not_found") {
|
if (err.value && err.value === "path_not_found") {
|
||||||
if (path !== "/" && path !== "") {
|
if (path !== state.path[0].path && path !== "/" && path !== "") {
|
||||||
console.debug("Path", path, "was not found, trying to navigate to parent")
|
console.debug("Path", path, "was not found, trying to navigate to parent")
|
||||||
navigate(fs_split_path(path).parent, push_history)
|
navigate(fs_split_path(path).parent, push_history)
|
||||||
}
|
}
|
||||||
@@ -56,18 +57,11 @@ export const reload = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const open_node = (node, push_history) => {
|
export const open_node = (node, push_history) => {
|
||||||
// We need to properly URL encode the file paths so they don't cause
|
|
||||||
// issues.. but we also want the slashes to stay clean. So here we encode
|
|
||||||
// the whole path, then decode the slashes
|
|
||||||
let cleanup_func = p => p.path_uri = encodeURIComponent(p.path).replaceAll("%2F", "/")
|
|
||||||
node.path.forEach(cleanup_func)
|
|
||||||
node.children.forEach(cleanup_func)
|
|
||||||
|
|
||||||
// Update window title and navigation history. If push_history is false we
|
// Update window title and navigation history. If push_history is false we
|
||||||
// still replace the URL with replaceState. This way the user is not greeted
|
// still replace the URL with replaceState. This way the user is not greeted
|
||||||
// to a 404 page when refreshing after renaming a file
|
// to a 404 page when refreshing after renaming a file
|
||||||
window.document.title = node.path[node.base_index].name+" ~ pixeldrain"
|
window.document.title = node.path[node.base_index].name+" ~ pixeldrain"
|
||||||
let url = "/d/"+node.path[0].id+node.path[node.base_index].path
|
let url = "/d"+ fs_encode_path(node.path[node.base_index].path)
|
||||||
if (push_history) {
|
if (push_history) {
|
||||||
window.history.pushState({}, window.document.title, url)
|
window.history.pushState({}, window.document.title, url)
|
||||||
} else {
|
} else {
|
||||||
@@ -90,7 +84,6 @@ export const open_node = (node, push_history) => {
|
|||||||
state.path = node.path
|
state.path = node.path
|
||||||
state.base = node.path[node.base_index]
|
state.base = node.path[node.base_index]
|
||||||
state.base_index = node.base_index
|
state.base_index = node.base_index
|
||||||
state.root = node.path[0]
|
|
||||||
state.children = node.children
|
state.children = node.children
|
||||||
state.permissions = node.permissions
|
state.permissions = node.permissions
|
||||||
|
|
||||||
@@ -131,7 +124,7 @@ export const open_sibling = async offset => {
|
|||||||
} 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.root.id, state.path[state.path.length - 2].path)
|
let resp = await fs_get_node(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.children)
|
sort_children(resp.children)
|
||||||
@@ -198,8 +191,8 @@ const sort_children = children => {
|
|||||||
|
|
||||||
// Capture browser back and forward navigation buttons
|
// Capture browser back and forward navigation buttons
|
||||||
window.onpopstate = (e) => {
|
window.onpopstate = (e) => {
|
||||||
// Get the part of the URL after the bucket ID and navigate to it
|
// Get the part of the URL after the fs root and navigate to it
|
||||||
let path = document.location.pathname.replace("/d/"+state.root.id, "")
|
let path = document.location.pathname.replace("/d/", "")
|
||||||
navigate(decodeURIComponent(path), false)
|
navigate(decodeURIComponent(path), false)
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@@ -37,7 +37,7 @@ const search = async (limit = 10) => {
|
|||||||
dispatch("loading", true)
|
dispatch("loading", true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
search_results = await fs_search(state.root.id, state.base.path, search_term, limit)
|
search_results = await fs_search(state.base.path, search_term, limit)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
try {
|
try {
|
||||||
error = JSON.parse(err).value
|
error = JSON.parse(err).value
|
||||||
@@ -95,15 +95,18 @@ const open_result = index => {
|
|||||||
|
|
||||||
|
|
||||||
<div class="search_bar highlight_shaded center">
|
<div class="search_bar highlight_shaded center">
|
||||||
<div>
|
|
||||||
Currently searching in <b>{state.base.path}</b>. Use the navigation buttons
|
|
||||||
above to search in a different location.
|
|
||||||
</div>
|
|
||||||
<form class="search_form" on:submit|preventDefault={submit_search}>
|
<form class="search_form" on:submit|preventDefault={submit_search}>
|
||||||
<i class="icon">search</i>
|
<i class="icon">search</i>
|
||||||
<!-- svelte-ignore a11y-autofocus -->
|
<!-- svelte-ignore a11y-autofocus -->
|
||||||
<input class="term" type="text" style="width: 100%;" bind:value={search_term} on:keyup={keyup} autofocus />
|
<input
|
||||||
<input class="submit" type="submit" value="Search"/>
|
class="term"
|
||||||
|
type="text"
|
||||||
|
placeholder="Type to search in {state.base.name}"
|
||||||
|
style="width: 100%;"
|
||||||
|
bind:value={search_term}
|
||||||
|
on:keyup={keyup}
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -119,10 +122,11 @@ const open_result = index => {
|
|||||||
class="node"
|
class="node"
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
<img src={fs_thumbnail_url(state.root.id, result, 32, 32)} class="node_icon" alt="icon"/>
|
<img src={fs_thumbnail_url(result, 32, 32)} class="node_icon" alt="icon"/>
|
||||||
</td>
|
</td>
|
||||||
<td class="node_name">
|
<td class="node_name">
|
||||||
{result}
|
<!-- Remove the search directory from the result -->
|
||||||
|
{result.slice(state.base.path.length+1)}
|
||||||
</td>
|
</td>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -160,9 +164,6 @@ const open_result = index => {
|
|||||||
.term {
|
.term {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
.submit {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory {
|
.directory {
|
||||||
display: table;
|
display: table;
|
||||||
|
@@ -39,7 +39,7 @@ $: {
|
|||||||
const share = async () => {
|
const share = async () => {
|
||||||
console.debug("Making file sharable", state.base)
|
console.debug("Making file sharable", state.base)
|
||||||
try {
|
try {
|
||||||
await fs_update(state.root.id, state.base.path, {shared: true})
|
await fs_update(state.base.path, {shared: true})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
alert(err)
|
alert(err)
|
||||||
|
@@ -95,7 +95,7 @@ let share = async () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if state.root.id === "me"}
|
{#if state.path[0].id === "me"}
|
||||||
<button on:click={() => dispatch("search")} class="toolbar_button" class:button_highlight={view === "search"}>
|
<button on:click={() => dispatch("search")} class="toolbar_button" class:button_highlight={view === "search"}>
|
||||||
<i class="icon">search</i> Search
|
<i class="icon">search</i> Search
|
||||||
</button>
|
</button>
|
||||||
@@ -121,7 +121,7 @@ let share = async () => {
|
|||||||
<i class="icon">help</i> Deta<u>i</u>ls
|
<i class="icon">help</i> Deta<u>i</u>ls
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if state.base.path !== "/"}
|
{#if state.path.length > 1}
|
||||||
<button on:click={() => edit_window.edit(state.base, true)} class="toolbar_button" class:button_highlight={edit_visible}>
|
<button on:click={() => edit_window.edit(state.base, true)} class="toolbar_button" class:button_highlight={edit_visible}>
|
||||||
<i class="icon">edit</i> <u>E</u>dit
|
<i class="icon">edit</i> <u>E</u>dit
|
||||||
</button>
|
</button>
|
||||||
|
@@ -12,9 +12,7 @@ let create_dir = () => {
|
|||||||
let form = new FormData()
|
let form = new FormData()
|
||||||
form.append("type", "dir")
|
form.append("type", "dir")
|
||||||
|
|
||||||
fs_mkdir(
|
fs_mkdir(state.base.path+"/"+new_dir_name).then(resp => {
|
||||||
state.root.id, state.base.path+"/"+new_dir_name,
|
|
||||||
).then(resp => {
|
|
||||||
new_dir_name = "" // Clear input field
|
new_dir_name = "" // Clear input field
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
if (err.value && err.value === "node_already_exists") {
|
if (err.value && err.value === "node_already_exists") {
|
||||||
|
@@ -75,7 +75,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(state.root.id, child.path))
|
promises.push(fs_delete(child.path))
|
||||||
})
|
})
|
||||||
|
|
||||||
// Wait for all the promises to finish
|
// Wait for all the promises to finish
|
||||||
|
@@ -19,7 +19,7 @@ export let show_hidden = false
|
|||||||
<div
|
<div
|
||||||
class="icon_container"
|
class="icon_container"
|
||||||
class:cover={fs_node_type(child) === "image" || fs_node_type(child) === "video"}
|
class:cover={fs_node_type(child) === "image" || fs_node_type(child) === "video"}
|
||||||
style='background-image: url("{fs_node_icon(state.root.id, child, 256, 256)}");'>
|
style='background-image: url("{fs_node_icon(child, 256, 256)}");'>
|
||||||
</div>
|
</div>
|
||||||
{child.name}
|
{child.name}
|
||||||
</a>
|
</a>
|
||||||
|
@@ -25,7 +25,7 @@ export let show_hidden = false
|
|||||||
class:hidden={child.name.startsWith(".") && !show_hidden}
|
class:hidden={child.name.startsWith(".") && !show_hidden}
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
<img src={fs_node_icon(state.root.id, child, 32, 32)} class="node_icon" alt="icon"/>
|
<img src={fs_node_icon(child, 32, 32)} class="node_icon" alt="icon"/>
|
||||||
</td>
|
</td>
|
||||||
<td class="node_name">
|
<td class="node_name">
|
||||||
{child.name}
|
{child.name}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher, onMount } from 'svelte'
|
import { createEventDispatcher, onMount } from 'svelte'
|
||||||
import { fs_file_url } from "../FilesystemUtil.js";
|
import { fs_path_url } from '../FilesystemUtil';
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let state
|
export let state
|
||||||
@@ -53,7 +53,7 @@ onMount(() => {
|
|||||||
<audio
|
<audio
|
||||||
bind:this={player}
|
bind:this={player}
|
||||||
class="player"
|
class="player"
|
||||||
src={fs_file_url(state.root.id, state.base.path)}
|
src={fs_path_url(state.base.path)}
|
||||||
autoplay="autoplay"
|
autoplay="autoplay"
|
||||||
controls="controls"
|
controls="controls"
|
||||||
on:pause={() => playing = false }
|
on:pause={() => playing = false }
|
||||||
|
@@ -9,7 +9,7 @@ export let state
|
|||||||
|
|
||||||
<h1>{state.base.name}</h1>
|
<h1>{state.base.name}</h1>
|
||||||
|
|
||||||
<IconBlock icon_href={fs_thumbnail_url(state.root.id, state.base.path, 256, 256)}>
|
<IconBlock icon_href={fs_thumbnail_url(state.base.path, 256, 256)}>
|
||||||
Type: {state.base.file_type}<br/>
|
Type: {state.base.file_type}<br/>
|
||||||
No preview is available for this file type. Download to view it locally.
|
No preview is available for this file type. Download to view it locally.
|
||||||
<br/>
|
<br/>
|
||||||
|
@@ -18,9 +18,15 @@ export let edit_window
|
|||||||
export let state
|
export let state
|
||||||
let viewer
|
let viewer
|
||||||
let viewer_type = ""
|
let viewer_type = ""
|
||||||
|
let last_path = ""
|
||||||
|
|
||||||
$: state_update(state.base)
|
$: state_update(state.base)
|
||||||
const state_update = async (base) => {
|
const state_update = async (base) => {
|
||||||
|
if (base.path === last_path) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
last_path = base.path
|
||||||
|
|
||||||
// Update the viewer area with the right viewer type
|
// Update the viewer area with the right viewer type
|
||||||
viewer_type = fs_node_type(base)
|
viewer_type = fs_node_type(base)
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { fs_file_url } from "../FilesystemUtil.js";
|
import { fs_path_url } from "../FilesystemUtil";
|
||||||
|
|
||||||
|
|
||||||
export let state
|
export let state
|
||||||
let container
|
let container
|
||||||
@@ -50,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_file_url(state.root.id, state.base.path)}
|
src={fs_path_url(state.base.path)}
|
||||||
alt="no description available" />
|
alt="no description available" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import { fs_file_url } from "../FilesystemUtil.js";
|
import { fs_path_url } from "../FilesystemUtil";
|
||||||
|
|
||||||
export let state
|
export let state
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<iframe
|
<iframe
|
||||||
class="container"
|
class="container"
|
||||||
src={"/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(fs_file_url(state.root.id, state.base.path))}
|
src={"/res/misc/pdf-viewer/web/viewer.html?file="+encodeURIComponent(fs_path_url(state.base.path))}
|
||||||
title="PDF viewer">
|
title="PDF viewer">
|
||||||
</iframe>
|
</iframe>
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { fs_file_url } from "../FilesystemUtil";
|
import { fs_path_url } from "../FilesystemUtil";
|
||||||
|
|
||||||
export let state
|
export let state
|
||||||
let text_pre
|
let text_pre
|
||||||
@@ -14,7 +14,7 @@ export const set_file = file => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(fs_file_url(state.root.id, file.path)).then(resp => {
|
fetch(fs_path_url(file.path)).then(resp => {
|
||||||
if (!resp.ok) { return Promise.reject(resp.status) }
|
if (!resp.ok) { return Promise.reject(resp.status) }
|
||||||
return resp.text()
|
return resp.text()
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
|
@@ -6,7 +6,7 @@ import { copy_text } from "../../util/Util.svelte";
|
|||||||
import TorrentItem from "./TorrentItem.svelte"
|
import TorrentItem from "./TorrentItem.svelte"
|
||||||
import IconBlock from "../../file_viewer/viewers/IconBlock.svelte";
|
import IconBlock from "../../file_viewer/viewers/IconBlock.svelte";
|
||||||
import TextBlock from "../../file_viewer/viewers/TextBlock.svelte";
|
import TextBlock from "../../file_viewer/viewers/TextBlock.svelte";
|
||||||
import { fs_file_url, fs_node_icon } from "../FilesystemUtil";
|
import { fs_node_icon, fs_path_url } from "../FilesystemUtil";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ export const update = async () => {
|
|||||||
dispatch("loading", true)
|
dispatch("loading", true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let resp = await fetch(fs_file_url(state.root.id, state.base.path)+"?torrent_info")
|
let resp = await fetch(fs_path_url(state.base.path)+"?torrent_info")
|
||||||
|
|
||||||
if (resp.status >= 400) {
|
if (resp.status >= 400) {
|
||||||
let json = await resp.json()
|
let json = await resp.json()
|
||||||
@@ -75,7 +75,7 @@ const copy_magnet = () => {
|
|||||||
|
|
||||||
<h1>{state.base.name}</h1>
|
<h1>{state.base.name}</h1>
|
||||||
|
|
||||||
<IconBlock icon_href={fs_node_icon(state.root.id, state.base, 256, 256)}>
|
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||||
{#if status === "finished"}
|
{#if status === "finished"}
|
||||||
Created by: {torrent.created_by}<br/>
|
Created by: {torrent.created_by}<br/>
|
||||||
Comment: {torrent.comment}<br/>
|
Comment: {torrent.comment}<br/>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount, createEventDispatcher, tick } from "svelte";
|
import { onMount, createEventDispatcher, tick } from "svelte";
|
||||||
import { fs_file_url } from "../FilesystemUtil";
|
import { fs_path_url } from "../FilesystemUtil";
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let state
|
export let state
|
||||||
@@ -100,7 +100,7 @@ const fullscreen = () => {
|
|||||||
on:play={() => playing = true }
|
on:play={() => playing = true }
|
||||||
on:ended={() => dispatch("next", {})}
|
on:ended={() => dispatch("next", {})}
|
||||||
>
|
>
|
||||||
<source src={fs_file_url(state.root.id, state.base.path)} type={state.base.file_type} />
|
<source src={fs_path_url(state.base.path)} type={state.base.file_type} />
|
||||||
</video>
|
</video>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -4,7 +4,7 @@ import { formatDataVolume, formatDate } from "../../util/Formatting.svelte"
|
|||||||
import ZipItem from "./ZipItem.svelte";
|
import ZipItem from "./ZipItem.svelte";
|
||||||
import IconBlock from "../../file_viewer/viewers/IconBlock.svelte";
|
import IconBlock from "../../file_viewer/viewers/IconBlock.svelte";
|
||||||
import TextBlock from "../../file_viewer/viewers/TextBlock.svelte";
|
import TextBlock from "../../file_viewer/viewers/TextBlock.svelte";
|
||||||
import { fs_file_url, fs_node_icon } from "../FilesystemUtil";
|
import { fs_node_icon, fs_path_url } from "../FilesystemUtil";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export const update = async () => {
|
|||||||
dispatch("loading", true)
|
dispatch("loading", true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let resp = await fetch(fs_file_url(state.root.id, state.base.path)+"?zip_info")
|
let resp = await fetch(fs_path_url(state.base.path)+"?zip_info")
|
||||||
|
|
||||||
if (resp.status >= 400) {
|
if (resp.status >= 400) {
|
||||||
status = "parse_failed"
|
status = "parse_failed"
|
||||||
@@ -61,7 +61,7 @@ const recursive_size = (file) => {
|
|||||||
|
|
||||||
<h1>{state.base.name}</h1>
|
<h1>{state.base.name}</h1>
|
||||||
|
|
||||||
<IconBlock icon_href={fs_node_icon(state.root.id, state.base, 256, 256)}>
|
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||||
Compressed size: {formatDataVolume(state.base.file_size, 3)}<br/>
|
Compressed size: {formatDataVolume(state.base.file_size, 3)}<br/>
|
||||||
Uncompressed size: {formatDataVolume(uncomp_size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
Uncompressed size: {formatDataVolume(uncomp_size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
||||||
Uploaded on: {formatDate(state.base.created, true, true, true)}
|
Uploaded on: {formatDate(state.base.created, true, true, true)}
|
||||||
|
Reference in New Issue
Block a user