feat(drag&drop): no drop zone on search page
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
import Icon from '$lib/icons/Icon.svelte';
|
import Icon from '$lib/icons/Icon.svelte';
|
||||||
import { t } from '$lib/i18n/index.svelte';
|
import { t } from '$lib/i18n/index.svelte';
|
||||||
import { files as filesStore } from '$lib/stores/files.svelte';
|
import { files as filesStore } from '$lib/stores/files.svelte';
|
||||||
|
import { ui } from '$lib/stores/ui.svelte';
|
||||||
import { formatBytes } from '$lib/utils/format';
|
import { formatBytes } from '$lib/utils/format';
|
||||||
import { formatDate, iconNameFromClass, fileIconKindClass } from '$lib/utils/display';
|
import { formatDate, iconNameFromClass, fileIconKindClass } from '$lib/utils/display';
|
||||||
|
|
||||||
@@ -202,10 +203,61 @@
|
|||||||
void dateFilter;
|
void dateFilter;
|
||||||
void run(query);
|
void run(query);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page-wide OS drag/drop guard.
|
||||||
|
*
|
||||||
|
* `/search` has no upload path, but without capturing the drop the
|
||||||
|
* browser's default handler navigates to the dropped file — the tab
|
||||||
|
* REPLACES the app with the file itself, which is data-loss-esque
|
||||||
|
* (user loses their in-progress search + any unsaved UI state).
|
||||||
|
* The `ResourceList`-based views (`/photos`, `/shared`, `/trash`, …)
|
||||||
|
* already fire a "wrong drop zone" toast via their `.rl-root`
|
||||||
|
* wrapper when `enableSystemDrop` is false — this handler brings
|
||||||
|
* `/search` to the same contract, and covers the whole viewport
|
||||||
|
* (not just a list surface) so drops on the sticky header /
|
||||||
|
* result-card margins are caught too. Same toast copy + "Go to
|
||||||
|
* Files" action as `ResourceList` for a consistent recovery UX.
|
||||||
|
*/
|
||||||
|
function onWindowDragOver(e: DragEvent) {
|
||||||
|
if (!e.dataTransfer?.types?.includes('Files')) return;
|
||||||
|
if (e.defaultPrevented) return;
|
||||||
|
e.preventDefault();
|
||||||
|
// `dropEffect = 'none'` would tell the browser to REJECT the
|
||||||
|
// drop before `drop` fires — the toast path below never runs.
|
||||||
|
// Accept at the pointer level and let `onWindowDrop` decide.
|
||||||
|
if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
|
||||||
|
}
|
||||||
|
function onWindowDrop(e: DragEvent) {
|
||||||
|
if (!e.dataTransfer?.types?.includes('Files')) return;
|
||||||
|
if (e.defaultPrevented) return;
|
||||||
|
e.preventDefault();
|
||||||
|
ui.notify(
|
||||||
|
t(
|
||||||
|
'resource_list.wrong_drop_zone_msg',
|
||||||
|
'Uploads only work in Files — open the Files section and drop there.'
|
||||||
|
),
|
||||||
|
'warning',
|
||||||
|
6000,
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
action: {
|
||||||
|
label: t('resource_list.wrong_drop_zone_action', 'Go to Files'),
|
||||||
|
// Best-effort recovery — the drop's `DataTransfer` is
|
||||||
|
// discarded once this handler returns (browsers don't
|
||||||
|
// persist it across a navigation), so we land the
|
||||||
|
// user in `/files` where they can re-drag from the OS.
|
||||||
|
onClick: () => goto(resolve('/files'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head><title>{t('search.title', 'Search')} · OxiCloud</title></svelte:head>
|
<svelte:head><title>{t('search.title', 'Search')} · OxiCloud</title></svelte:head>
|
||||||
|
|
||||||
|
<svelte:window ondragover={onWindowDragOver} ondrop={onWindowDrop} />
|
||||||
|
|
||||||
<div class="page-sticky-header search-head">
|
<div class="page-sticky-header search-head">
|
||||||
<h1 class="page-title">
|
<h1 class="page-title">
|
||||||
{#if query}{t('search.results_for', { q: query }, 'Results for “{{q}}”')}{:else}{t(
|
{#if query}{t('search.results_for', { q: query }, 'Results for “{{q}}”')}{:else}{t(
|
||||||
|
|||||||
Reference in New Issue
Block a user