chore: add drag-and-drop box to Launch page
This commit is contained in:
1 parent
00958d5238
commit
2d1941db33
3 files changed
+81
-5
No files matched your search
@@ -0,0 +1,52 @@
|
|||||||
|
import { listen } from "@tauri-apps/api/event";
|
||||||
|
import { onDestroy } from "svelte";
|
||||||
|
|
||||||
|
type TauriDragDropEvent = {
|
||||||
|
paths: string[];
|
||||||
|
position: { x: number; y: number };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDropZone = ({ onDrop }: { onDrop: (paths: string[]) => void }) => {
|
||||||
|
let element = $state<HTMLDivElement | null>(null);
|
||||||
|
let dragIn = $state(false);
|
||||||
|
let isDraggingOverApp = $state(false);
|
||||||
|
|
||||||
|
const isOver = (x: number, y: number) => {
|
||||||
|
if (!element) return false;
|
||||||
|
const el = document.elementFromPoint(x, y);
|
||||||
|
return element === el || element.contains(el); // ← fix
|
||||||
|
};
|
||||||
|
|
||||||
|
const dropUnlisten = listen<TauriDragDropEvent>("tauri://drag-drop", (e) => {
|
||||||
|
const { x, y } = e.payload.position;
|
||||||
|
if (isOver(x, y)) {
|
||||||
|
onDrop(e.payload.paths);
|
||||||
|
}
|
||||||
|
dragIn = false;
|
||||||
|
isDraggingOverApp = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const overUnlisten = listen<TauriDragDropEvent>("tauri://drag-over", (e) => {
|
||||||
|
const { x, y } = e.payload.position;
|
||||||
|
isDraggingOverApp = true;
|
||||||
|
dragIn = isOver(x, y);
|
||||||
|
});
|
||||||
|
|
||||||
|
const leaveUnlisten = listen("tauri://drag-leave", () => {
|
||||||
|
dragIn = false;
|
||||||
|
isDraggingOverApp = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(async () => {
|
||||||
|
(await dropUnlisten)();
|
||||||
|
(await overUnlisten)();
|
||||||
|
(await leaveUnlisten)();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
get ref() { return element; },
|
||||||
|
set ref(el: HTMLDivElement | null) { element = el; },
|
||||||
|
get dragIn() { return dragIn; },
|
||||||
|
get isDraggingOverApp() { return isDraggingOverApp; },
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
Paintbrush,
|
Paintbrush,
|
||||||
Trash,
|
Trash,
|
||||||
CloudDownload,
|
CloudDownload,
|
||||||
|
Import,
|
||||||
} from 'lucide-svelte';
|
} from 'lucide-svelte';
|
||||||
import NumberFlow from '@number-flow/svelte';
|
import NumberFlow from '@number-flow/svelte';
|
||||||
import * as AlertDialog from '@/components/ui/alert-dialog';
|
import * as AlertDialog from '@/components/ui/alert-dialog';
|
||||||
@@ -62,7 +63,7 @@
|
|||||||
setCurrentTimeGlobalMedia,
|
setCurrentTimeGlobalMedia,
|
||||||
urlIsValidImage,
|
urlIsValidImage,
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { fade, fly } from 'svelte/transition';
|
import { fade, fly, scale } from 'svelte/transition';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import Label from '@/components/ui/label/label.svelte';
|
import Label from '@/components/ui/label/label.svelte';
|
||||||
import {
|
import {
|
||||||
@@ -123,8 +124,9 @@
|
|||||||
import { sileo } from 'sileo';
|
import { sileo } from 'sileo';
|
||||||
import ScrollContainer from '@/components/ui/scroll-container/ScrollContainer.svelte';
|
import ScrollContainer from '@/components/ui/scroll-container/ScrollContainer.svelte';
|
||||||
import { deleteTheme, downloadTheme, loadTheme } from '@/themes';
|
import { deleteTheme, downloadTheme, loadTheme } from '@/themes';
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { listen } from "@tauri-apps/api/event";
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
import { useDropZone } from '@/dropZone.svelte';
|
||||||
|
|
||||||
let selectedView = $state('home');
|
let selectedView = $state('home');
|
||||||
let progress = $state(-1);
|
let progress = $state(-1);
|
||||||
@@ -136,6 +138,12 @@
|
|||||||
|
|
||||||
let downloadingUpdate = $state(false);
|
let downloadingUpdate = $state(false);
|
||||||
|
|
||||||
|
let dragAndDrop = useDropZone({
|
||||||
|
onDrop: async (file) => {
|
||||||
|
console.log('dropped', file);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
let downloadingEZPPFiles = $state(false);
|
let downloadingEZPPFiles = $state(false);
|
||||||
let cleanup = $state(false);
|
let cleanup = $state(false);
|
||||||
|
|
||||||
@@ -757,6 +765,21 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if dragAndDrop.isDraggingOverApp}
|
||||||
|
<div
|
||||||
|
class="fixed top-0 left-0 w-full h-full z-50 flex items-center justify-center bg-black/10 backdrop-blur-sm pointer-events-none"
|
||||||
|
transition:fade={{ duration: 300 }}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-[90vw] h-[90vh] flex flex-col items-center justify-center bg-theme-900 border border-theme-800 rounded-lg"
|
||||||
|
transition:scale={{ start: 0.7, duration: 300 }}
|
||||||
|
>
|
||||||
|
<Import size={64} />
|
||||||
|
<p>Drag and Drop a .ezpplauncher-theme file here to import</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<AlertDialog.Root open={launchError !== undefined}>
|
<AlertDialog.Root open={launchError !== undefined}>
|
||||||
<AlertDialog.Content class="bg-theme-950 border-theme-800 p-0 max-w-[90vw]">
|
<AlertDialog.Content class="bg-theme-950 border-theme-800 p-0 max-w-[90vw]">
|
||||||
<div
|
<div
|
||||||
@@ -917,7 +940,7 @@
|
|||||||
</AlertDialog.Content>
|
</AlertDialog.Content>
|
||||||
</AlertDialog.Root>
|
</AlertDialog.Root>
|
||||||
|
|
||||||
<div class="grid grid-cols-[0.085fr_1fr] h-[100vh] relative">
|
<div class="grid grid-cols-[0.085fr_1fr] h-[100vh] relative" bind:this={dragAndDrop.ref}>
|
||||||
<div
|
<div
|
||||||
class="p-3 border-r border-r-theme-900 flex flex-col items-center gap-2 z-10 bg-black/40 backdrop-blur-sm"
|
class="p-3 border-r border-r-theme-900 flex flex-col items-center gap-2 z-10 bg-black/40 backdrop-blur-sm"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
getVersion,
|
getVersion,
|
||||||
isValidOsuFolder,
|
isValidOsuFolder,
|
||||||
} from '@/osuUtil';
|
} from '@/osuUtil';
|
||||||
|
import { dev } from '$app/environment';
|
||||||
|
|
||||||
let selectedStep = $state(1);
|
let selectedStep = $state(1);
|
||||||
const steps = ['Welcome', 'Locate your osu! Installation', 'Appearance Settings'];
|
const steps = ['Welcome', 'Locate your osu! Installation', 'Appearance Settings'];
|
||||||
@@ -371,7 +372,7 @@
|
|||||||
else selectedStep = Math.min(selectedStep + 1, steps.length);
|
else selectedStep = Math.min(selectedStep + 1, steps.length);
|
||||||
}}
|
}}
|
||||||
disabled={selectedStep > steps.length ||
|
disabled={selectedStep > steps.length ||
|
||||||
(selectedStep === 2 && osuInstallPath.length <= 0)}
|
(selectedStep === 2 && (!dev && osuInstallPath.length <= 0))}
|
||||||
>{selectedStep >= steps.length ? 'Finish' : 'Next'}</Button
|
>{selectedStep >= steps.length ? 'Finish' : 'Next'}</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user