mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-04 00:47:01 +01:00
ui: touch parity, saves that survive outages, edits that do not collide
PUT /api/nodes/{id} takes base_updated_at and answers 409 when the node
was saved since; the editor sends it, so a save from another tab, the
phone or the SFTP mount is no longer overwritten in silence. :w! and
:wq! now force the write.
An autosave the server could not take is kept and retried with backoff,
and at once on the online event; network failures say "the server
cannot be reached" rather than "Failed to fetch". At boot that is no
longer shown as a login screen. A session that expires mid-edit shows
the login with a note, and logging back in resumes the open draft.
Folder listings and the media list are read page by page, so more than
500 children are no longer cut off. Search results carry the space and
folder they sit in, and the overview's recent list includes files.
Embedding uploads report progress, like uploads into a folder.
On touch devices vim is off by default. Each row has an actions sheet
(rename, move, share, seal, delete), folders start with a .. row, and
the dock gains today's entry, upload, search all spaces, drop for a
marked node, help, and the board's list, reorder, rename and delete.
The agenda gets a done button per card and a button for today's entry.
Sharing a folder or a file is refused in the client. :mv .. in a search
moves up from the match's own folder. Files dropped outside the list or
editor no longer navigate the tab away. The public share view renders
/n/ links as plain text, and tells a network error from a dead link.
This commit is contained in:
1 parent
ee13ae44fa
commit
2733ac1a3a
15 files changed
+472
-74
No files matched your search
+19
-2
@@ -11,6 +11,7 @@
|
||||
import Login from './lib/Login.svelte'
|
||||
import Overview from './lib/Overview.svelte'
|
||||
import MediaBrowser from './lib/MediaBrowser.svelte'
|
||||
import Actions from './lib/Actions.svelte'
|
||||
import Prompt from './lib/Prompt.svelte'
|
||||
import SecretPrompt from './lib/SecretPrompt.svelte'
|
||||
import Rail from './lib/Rail.svelte'
|
||||
@@ -65,6 +66,10 @@
|
||||
cmdline = initial
|
||||
}
|
||||
hooks.openOverview = () => void openOverview()
|
||||
hooks.openGlobalSearch = () => {
|
||||
cmdGlobal = true
|
||||
cmdline = '/'
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
@@ -167,6 +172,18 @@
|
||||
await workspace.guard(() => workspace.importFolder(files, root))
|
||||
}
|
||||
|
||||
/*
|
||||
* Files let go anywhere but the list or the editor would make the browser
|
||||
* open them in place of the app. The places that take files say so
|
||||
* themselves; everywhere else refuses the drop, and says where it goes.
|
||||
*/
|
||||
function strayDrop(event: DragEvent) {
|
||||
if (event.defaultPrevented || !event.dataTransfer?.types.includes('Files')) return
|
||||
event.preventDefault()
|
||||
event.dataTransfer.dropEffect = 'none'
|
||||
if (event.type === 'drop') workspace.say('drop files on the list to put them in this folder, or into the editor to embed them', 'error')
|
||||
}
|
||||
|
||||
// What the empty pane offers, in the key/value shape of a status readout.
|
||||
// Keys are keycaps, so `o` and `O` cannot be read as the same key.
|
||||
const offers: [string[], string][] = [
|
||||
@@ -636,7 +653,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window {onkeydown} />
|
||||
<svelte:window {onkeydown} ondragover={strayDrop} ondrop={strayDrop} />
|
||||
|
||||
{#if shareToken}
|
||||
<Shared token={shareToken} shareKey={shareKey} />
|
||||
@@ -718,7 +735,7 @@
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions, a11y_no_noninteractive_tabindex -->
|
||||
<div class="overlay" tabindex="-1" bind:this={overlayEl} onclick={(e) => e.target === e.currentTarget && (workspace.overlay = 'none')}
|
||||
>
|
||||
{#if workspace.overlay === 'help'}<Help />{:else if workspace.overlay === 'overview'}<Overview />{:else if workspace.overlay === 'agenda'}<Agenda />{:else}<MediaBrowser />{/if}
|
||||
{#if workspace.overlay === 'help'}<Help />{:else if workspace.overlay === 'overview'}<Overview />{:else if workspace.overlay === 'agenda'}<Agenda />{:else if workspace.overlay === 'actions'}<Actions />{:else}<MediaBrowser />{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user