Skip to content

Commit 1d2cce1

Browse files
committed
- Properly title icon buttons
- Add btn-danger utility - Add blacklist patterns for directory comparison
1 parent f76a4bf commit 1d2cce1

File tree

6 files changed

+122
-21
lines changed

6 files changed

+122
-21
lines changed

web/src/app.css

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,30 @@
9494
}
9595
}
9696

97+
@utility btn-primary-hover {
98+
@apply bg-blue-600;
99+
}
97100
@utility btn-primary {
98101
@apply bg-primary text-white;
99102
&:hover {
100-
@apply bg-blue-600;
103+
@apply btn-primary-hover;
101104
}
102105
&:active {
103106
@apply bg-blue-700;
104107
}
105108
@apply transition-colors duration-100 ease-in-out;
106109
}
107110

111+
@utility btn-danger {
112+
@apply bg-red-500 text-white;
113+
&:hover {
114+
@apply bg-red-600;
115+
}
116+
&:active {
117+
@apply bg-red-700;
118+
}
119+
}
120+
108121
.png-bg {
109122
background: url("/png.gif") right bottom var(--color-gray-300);
110123
}

web/src/lib/components/settings-popover/SettingsPopover.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
let { children, ...restProps }: WithChildren<RestProps> = $props();
1212
1313
const defTriggerProps = {
14+
title: "Settings",
1415
class: "size-6 rounded-md flex items-center justify-center text-primary btn-ghost data-[state=open]:btn-ghost-visible",
1516
};
1617

web/src/routes/diff/+page.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,15 @@
9090

9191
{#snippet sidebarToggle()}
9292
<button
93+
title={viewer.sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
9394
type="button"
9495
class="flex size-6 items-center justify-center rounded-md btn-ghost text-primary"
9596
onclick={() => (viewer.sidebarCollapsed = !viewer.sidebarCollapsed)}
9697
>
9798
{#if viewer.sidebarCollapsed}
98-
<span class="iconify size-4 shrink-0 octicon--sidebar-collapse-16"></span>
99+
<span class="iconify size-4 shrink-0 octicon--sidebar-collapse-16" aria-hidden="true"></span>
99100
{:else}
100-
<span class="iconify size-4 shrink-0 octicon--sidebar-expand-16"></span>
101+
<span class="iconify size-4 shrink-0 octicon--sidebar-expand-16" aria-hidden="true"></span>
101102
{/if}
102103
</button>
103104
{/snippet}

web/src/routes/diff/ActionsPopover.svelte

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
</script>
99

1010
<Popover.Root bind:open>
11-
<Popover.Trigger
12-
aria-label="Actions"
13-
class="flex size-6 items-center justify-center self-center rounded-md btn-ghost p-0.5 data-[state=open]:btn-ghost-visible"
14-
>
11+
<Popover.Trigger title="Actions" class="flex size-6 items-center justify-center self-center rounded-md btn-ghost p-0.5 data-[state=open]:btn-ghost-visible">
1512
<span aria-hidden="true" class="iconify size-4 bg-primary octicon--kebab-horizontal-16"></span>
1613
</Popover.Trigger>
1714
<Popover.Portal>

web/src/routes/diff/InfoPopup.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<Popover.Root>
88
<Popover.Trigger
9-
aria-label="Actions"
9+
title="Information"
1010
class="flex size-6 items-center justify-center self-center rounded-md btn-ghost p-0.5 data-[state=open]:btn-ghost-visible"
1111
>
1212
<span aria-hidden="true" class="iconify size-4 bg-primary octicon--info-16"></span>

web/src/routes/diff/LoadDiffDialog.svelte

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { type FileStatus, getGithubUsername, GITHUB_URL_PARAM, installGithubApp, loginWithGithub, logoutGithub } from "$lib/github.svelte";
3-
import { Button, Dialog, Separator } from "bits-ui";
3+
import { Button, Dialog, Separator, Popover } from "bits-ui";
44
import InfoPopup from "./InfoPopup.svelte";
55
import { page } from "$app/state";
66
import { goto } from "$app/navigation";
@@ -12,6 +12,7 @@
1212
import { createTwoFilesPatch } from "diff";
1313
import DirectorySelect from "$lib/components/files/DirectorySelect.svelte";
1414
import { DirectoryEntry, FileEntry } from "$lib/components/files/index.svelte";
15+
import { SvelteSet } from "svelte/reactivity";
1516
1617
const viewer = MultiFileDiffViewerState.get();
1718
@@ -23,6 +24,20 @@
2324
let fileB = $state<File | undefined>(undefined);
2425
let dirA = $state<DirectoryEntry | undefined>(undefined);
2526
let dirB = $state<DirectoryEntry | undefined>(undefined);
27+
let dirBlacklistInput = $state<string>("");
28+
const defaultDirBlacklist = [".git/"];
29+
let dirBlacklist = new SvelteSet(defaultDirBlacklist);
30+
let dirBlacklistRegexes = $derived.by(() => {
31+
return Array.from(dirBlacklist).map((pattern) => new RegExp(pattern));
32+
});
33+
34+
function addBlacklistEntry() {
35+
if (dirBlacklistInput === "") {
36+
return;
37+
}
38+
dirBlacklist.add(dirBlacklistInput);
39+
dirBlacklistInput = "";
40+
}
2641
2742
onMount(async () => {
2843
const url = page.url.searchParams.get(GITHUB_URL_PARAM);
@@ -101,15 +116,17 @@
101116
file: File;
102117
};
103118
104-
// TODO: option to respect gitignore?
105119
async function compareDirs() {
106120
if (!dirA || !dirB) {
107121
alert("Both directories must be selected to compare.");
108122
return;
109123
}
110124
111-
const entriesA: ProtoFileDetails[] = flatten(dirA);
112-
const entriesB: ProtoFileDetails[] = flatten(dirB);
125+
const blacklist = (entry: ProtoFileDetails) => {
126+
return !dirBlacklistRegexes.some((pattern) => pattern.test(entry.path));
127+
};
128+
const entriesA: ProtoFileDetails[] = flatten(dirA).filter(blacklist);
129+
const entriesB: ProtoFileDetails[] = flatten(dirB).filter(blacklist);
113130
114131
const fileDetails: FileDetails[] = [];
115132
@@ -312,15 +329,72 @@
312329
}
313330
</script>
314331

332+
{#snippet blacklistPopoverContent()}
333+
<div class="mb-2 flex bg-neutral-2 py-2 ps-2 pe-6">
334+
<span class="me-1 text-lg font-semibold">Blacklist patterns</span>
335+
<InfoPopup>Regex patterns for directories and files to ignore.</InfoPopup>
336+
</div>
337+
<div class="flex items-center gap-1 px-2">
338+
<div class="flex">
339+
<input
340+
bind:value={dirBlacklistInput}
341+
onkeydown={(e) => {
342+
if (e.key === "Enter") {
343+
addBlacklistEntry();
344+
}
345+
}}
346+
type="text"
347+
class="w-full rounded-l-md border-t border-b border-l px-2 py-1"
348+
/>
349+
<Button.Root title="Add blacklist entry" class="flex rounded-r-md btn-primary px-2 py-1" onclick={addBlacklistEntry}>
350+
<span class="iconify size-4 shrink-0 place-self-center octicon--plus-16" aria-hidden="true"></span>
351+
</Button.Root>
352+
</div>
353+
<Button.Root
354+
title="Reset blacklist to defaults"
355+
class="flex rounded-md btn-danger p-1"
356+
onclick={() => {
357+
dirBlacklist.clear();
358+
defaultDirBlacklist.forEach((entry) => {
359+
dirBlacklist.add(entry);
360+
});
361+
}}
362+
>
363+
<span class="iconify size-4 shrink-0 place-self-center octicon--undo-16" aria-hidden="true"></span>
364+
</Button.Root>
365+
</div>
366+
<ul class="m-2 max-h-96 overflow-y-auto rounded-md border">
367+
{#each dirBlacklist as entry (entry)}
368+
<li class="flex">
369+
<span class="grow border-b px-2 py-1">{entry}</span>
370+
<div class="border-b p-1 ps-0">
371+
<Button.Root
372+
title="Delete blacklist entry"
373+
class="flex rounded-md btn-danger p-1"
374+
onclick={() => {
375+
dirBlacklist.delete(entry);
376+
}}
377+
>
378+
<span class="iconify size-4 shrink-0 place-self-center octicon--trash-16" aria-hidden="true"></span>
379+
</Button.Root>
380+
</div>
381+
</li>
382+
{/each}
383+
{#if dirBlacklist.size === 0}
384+
<li class="px-2 py-1 text-em-med">No patterns added</li>
385+
{/if}
386+
</ul>
387+
{/snippet}
388+
315389
<Dialog.Root bind:open={modalOpen}>
316390
<Dialog.Trigger class="h-fit rounded-md btn-primary px-2 py-0.5" onclick={() => (dragActive = false)}>Load another diff</Dialog.Trigger>
317391
<Dialog.Portal>
318392
<Dialog.Overlay class="fixed inset-0 z-50 bg-black/50 dark:bg-white/20" />
319393
<Dialog.Content class="fixed top-1/2 left-1/2 z-50 w-192 max-w-[95%] -translate-x-1/2 -translate-y-1/2 rounded-md bg-neutral shadow-md">
320394
<header class="relative flex flex-row items-center justify-between rounded-t-md bg-neutral-2 p-4">
321395
<Dialog.Title class="text-xl font-semibold">Load a diff</Dialog.Title>
322-
<Dialog.Close class="flex size-6 items-center justify-center rounded-md btn-ghost text-primary">
323-
<span class="iconify octicon--x-16"></span>
396+
<Dialog.Close title="Close dialog" class="flex size-6 items-center justify-center rounded-md btn-ghost text-primary">
397+
<span class="iconify octicon--x-16" aria-hidden="true"></span>
324398
</Dialog.Close>
325399
</header>
326400

@@ -354,7 +428,7 @@
354428
<span class="iconify shrink-0 octicon--person-16"></span>
355429
{getGithubUsername()}
356430
</div>
357-
<Button.Root class="flex items-center gap-2 rounded-md bg-red-400 px-2 py-1 text-white hover:bg-red-500" onclick={logoutGithub}>
431+
<Button.Root class="flex items-center gap-2 rounded-md btn-danger px-2 py-1" onclick={logoutGithub}>
358432
<span class="iconify shrink-0 octicon--sign-out-16"></span>
359433
Sign out
360434
</Button.Root>
@@ -413,18 +487,33 @@
413487
</section>
414488

415489
<section>
416-
<h4 class="mb-2 font-semibold">Compare Directories</h4>
417-
<div class="flex flex-row items-center gap-1">
418-
<DirectorySelect bind:directory={dirA} placeholder="Directory A" />
419-
<span class="iconify size-4 shrink-0 octicon--arrow-right-16"></span>
420-
<DirectorySelect bind:directory={dirB} placeholder="Directory B" />
421-
<Button.Root onclick={compareDirs} class="rounded-md btn-primary px-2 py-1">Go</Button.Root>
490+
<div class="mb-2 flex items-center">
491+
<h4 class="me-1 font-semibold">Compare Directories</h4>
422492
<InfoPopup>
423493
Compares the entire contents of the directories, including subdirectories. Does not attempt to detect renames. When possible,
424494
preparing a unified diff (<code class="rounded-sm bg-neutral-2 px-1 py-0.5">.patch</code> file) using Git or another tool and loading
425495
it with the above button should be preferred.
426496
</InfoPopup>
427497
</div>
498+
<div class="flex items-center gap-1">
499+
<DirectorySelect bind:directory={dirA} placeholder="Directory A" />
500+
<span class="iconify size-4 shrink-0 octicon--arrow-right-16"></span>
501+
<DirectorySelect bind:directory={dirB} placeholder="Directory B" />
502+
<div class="flex">
503+
<Button.Root onclick={compareDirs} class="relative rounded-l-md btn-primary">
504+
<div class="px-2 py-1">Go</div>
505+
<div class="absolute top-0 right-0 h-full w-px bg-neutral-3/20"></div>
506+
</Button.Root>
507+
<Popover.Root>
508+
<Popover.Trigger title="Edit filters" class="flex rounded-r-md btn-primary p-2 data-[state=open]:btn-primary-hover">
509+
<span class="iconify size-4 shrink-0 place-self-center octicon--filter-16" aria-hidden="true"></span>
510+
</Popover.Trigger>
511+
<Popover.Content side="top" class="overflow-hidden rounded-md border bg-neutral">
512+
{@render blacklistPopoverContent()}
513+
</Popover.Content>
514+
</Popover.Root>
515+
</div>
516+
</div>
428517
</section>
429518
</section>
430519
</Dialog.Content>

0 commit comments

Comments
 (0)