Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/lib/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import type { DataWithDiagnostics, Profile } from './types';

export const notification = writable('');

export const localFile = writable<File | null>(null);
export const localData = writable<DataWithDiagnostics | Profile | null>(null);
87 changes: 85 additions & 2 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,99 @@
<script lang="ts">
import '../app.css';
import { notification } from '$lib/stores';
import { goto, invalidateAll } from '$app/navigation';
import { localData, localFile, notification } from '$lib/stores';
import { page } from '$app/stores';

$: if ($notification) {
setTimeout(() => ($notification = ''), 2000);
}

let dragTarget: EventTarget | null = null;
let validDragFile = false;

const onDragEnter = (e: DragEvent) => {
dragTarget = e.target;

if (!e.dataTransfer) return;

validDragFile = [...e.dataTransfer.items].some(
(item) => item.kind === 'file' && item.type === 'application/json'
);
};

const onDragLeave = (e: DragEvent) => {
if (e.target === dragTarget || !dragTarget || !e.target) {
dragTarget = null;
validDragFile = false;
}
};

const onDragOver = (e: DragEvent) => {
if (!e.dataTransfer) return;

const fileItems = [...e.dataTransfer.items].filter((item) => item.kind === 'file');

if (fileItems.length === 0) return;
e.preventDefault();

if (fileItems.some((item) => item.type === 'application/json')) {
e.dataTransfer.dropEffect = 'copy';
} else {
e.dataTransfer.dropEffect = 'none';
}
};
Comment on lines +31 to +44
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we care about the dragover event? Wouldn't dragenter have already captured the file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately dataTransfer.dropEffect (required for the ondrop event to fire) can only be written to inside the ondragover event. You could try merging onDragEnter into onDragOver, and removing the ondragenter event, but I recall that it didn't work quite right when I did that. (Which was before I had it fully working, to be fair)


const onDrop = (e: DragEvent) => {
dragTarget = null;
validDragFile = false;
if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
e.preventDefault();
$localFile = e.dataTransfer.files[0];
}
};

$: if ($localFile) {
const file = $localFile;
$localFile = null;

file.arrayBuffer().then((data) => {
try {
let string_data = new TextDecoder().decode(data);
$localData = JSON.parse(string_data);
const pathname = $page.url.pathname;
if (pathname === '/p' || pathname.startsWith('/p/')) {
invalidateAll();
} else {
goto('/p');
}
} catch (e) {
$notification = `Couldn't open ${file.name}: ${e}`;
}
});
}
</script>

<svelte:document
on:dragenter={onDragEnter}
on:dragleave={onDragLeave}
on:dragover={onDragOver}
on:drop={onDrop}
/>

<slot />

{#if validDragFile}
<div class="fixed left-0 top-0 h-dvh w-dvw bg-gray-900/60 p-10">
<div
class="pointer-events-none flex h-full w-full items-center justify-center rounded-3xl border-4 border-dashed border-green-500 bg-gray-900/80"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pointer-events-none is required, otherwise the overlay gets stuck if you drag a file over the <h1> and press Esc, might be a Firefox bug.

>
<h1 class="text-3xl">Drop profile JSON here</h1>
</div>
</div>
{/if}

{#if $notification}
<div class="fixed right-10 bottom-10 bg-gray-700/50 w-96 p-2 rounded-lg backdrop-blur-md">
<div class="fixed bottom-10 right-10 w-96 rounded-lg bg-gray-700/50 p-2 backdrop-blur-md">
{@html $notification}
</div>
{/if}
13 changes: 2 additions & 11 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { localData, notification } from '$lib/stores';
import { localFile } from '$lib/stores';
import logo from '../assets/logo.png';

$: {
Expand All @@ -12,16 +12,7 @@
let files: FileList | null = null;

$: if (files && files?.length > 0) {
const file = files[0];
file.arrayBuffer().then((data) => {
try {
let string_data = new TextDecoder().decode(data);
$localData = JSON.parse(string_data);
goto('/p');
} catch (e) {
$notification = `Couldn't open ${file.name}: ${e}`;
}
});
$localFile = files[0];
}
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/routes/p/[[id]]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<input
bind:value={query}
placeholder="Search entries..."
class="w-full mx-2 bg-neutral-900 focus:outline-none"
class="w-full px-2 bg-neutral-900 focus:outline-none"
/>
</div>
<table class="border-b w-full">
Expand Down