diff --git a/apps/matrix/apps/web/src/lib/components/chat/DropZoneOverlay.svelte b/apps/matrix/apps/web/src/lib/components/chat/DropZoneOverlay.svelte new file mode 100644 index 000000000..675058256 --- /dev/null +++ b/apps/matrix/apps/web/src/lib/components/chat/DropZoneOverlay.svelte @@ -0,0 +1,27 @@ + + +{#if visible} +
+
+
+ +
+
+

Datei hier ablegen

+

Bilder, Videos oder Dateien

+
+
+
+{/if} diff --git a/apps/matrix/apps/web/src/lib/components/chat/index.ts b/apps/matrix/apps/web/src/lib/components/chat/index.ts index cb77e5a01..06e82b842 100644 --- a/apps/matrix/apps/web/src/lib/components/chat/index.ts +++ b/apps/matrix/apps/web/src/lib/components/chat/index.ts @@ -7,3 +7,4 @@ export { default as MessageInput } from './MessageInput.svelte'; export { default as TypingIndicator } from './TypingIndicator.svelte'; export { default as CreateRoomDialog } from './CreateRoomDialog.svelte'; export { default as RoomSettingsPanel } from './RoomSettingsPanel.svelte'; +export { default as DropZoneOverlay } from './DropZoneOverlay.svelte'; diff --git a/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte b/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte index cb3965c76..3f3b5474e 100644 --- a/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte +++ b/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte @@ -1,6 +1,12 @@ {#if isMobile} @@ -228,7 +273,16 @@ -
+
+ + + {#if matrixStore.currentRoom} import { page } from '$app/stores'; import { matrixStore, type SimpleMessage } from '$lib/matrix'; - import { RoomHeader, Timeline, MessageInput } from '$lib/components/chat'; + import { RoomHeader, Timeline, MessageInput, DropZoneOverlay } from '$lib/components/chat'; import RoomSettingsPanel from '$lib/components/chat/RoomSettingsPanel.svelte'; import SearchDialog from '$lib/components/chat/SearchDialog.svelte'; import ForwardMessageDialog from '$lib/components/chat/ForwardMessageDialog.svelte'; @@ -26,6 +26,10 @@ let showSearch = $state(false); let showForward = $state(false); + // Drag & Drop state + let isDragging = $state(false); + let dragCounter = $state(0); + // Reply/Edit/Forward state let replyTo = $state(null); let editMessage = $state(null); @@ -178,6 +182,41 @@ function handleCallReject() { // Call rejected - UI will update automatically } + + // Drag & Drop handlers + function handleDragEnter(e: DragEvent) { + e.preventDefault(); + dragCounter++; + if (e.dataTransfer?.types.includes('Files')) { + isDragging = true; + } + } + + function handleDragLeave(e: DragEvent) { + e.preventDefault(); + dragCounter--; + if (dragCounter === 0) { + isDragging = false; + } + } + + function handleDragOver(e: DragEvent) { + e.preventDefault(); + } + + async function handleDrop(e: DragEvent) { + e.preventDefault(); + isDragging = false; + dragCounter = 0; + + const files = e.dataTransfer?.files; + if (!files?.length || !matrixStore.currentRoom) return; + + // Upload all dropped files sequentially + for (const file of files) { + await matrixStore.sendFile(file); + } + } @@ -188,7 +227,14 @@ ontouchmove={handleTouchMove} ontouchend={handleTouchEnd} ontouchcancel={handleTouchCancel} + ondragenter={handleDragEnter} + ondragleave={handleDragLeave} + ondragover={handleDragOver} + ondrop={handleDrop} > + + + {#if isSwiping && swipeProgress > 0}