Skip to content

Commit 5c7ea0f

Browse files
committed
Add no statuses selected text, fix cached state restoration with component reuse
1 parent 3ee1ce2 commit 5c7ea0f

File tree

3 files changed

+36
-31
lines changed

3 files changed

+36
-31
lines changed

web/src/lib/components/diff-filtering/DiffFilterDialog.svelte

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
<script lang="ts">
22
import { getFileStatusProps, MultiFileDiffViewerState } from "$lib/diff-viewer.svelte";
33
import { Button, Dialog, ToggleGroup } from "bits-ui";
4-
import { type FileNameFilterMode } from "./index.svelte";
4+
import { type FilePathFilterMode } from "./index.svelte";
55
import { FILE_STATUSES } from "$lib/github.svelte";
6+
import { slide } from "svelte/transition";
67
78
const viewer = MultiFileDiffViewerState.get();
89
const instance = viewer.filter;
910
10-
let newFileNameFilterInput = $state("");
11-
let newFileNameFilterMode: FileNameFilterMode = $state("exclude");
11+
let newFilePathFilterInput = $state("");
12+
let newFilePathFilterMode: FilePathFilterMode = $state("exclude");
1213
</script>
1314

1415
<Dialog.Root bind:open={viewer.diffFilterDialogOpen}>
@@ -41,6 +42,9 @@
4142
</ToggleGroup.Item>
4243
{/each}
4344
</ToggleGroup.Root>
45+
{#if instance.selectedFileStatuses.length === 0}
46+
<p transition:slide class="px-2 text-em-med italic">No file statuses selected; all files will be excluded.</p>
47+
{/if}
4448
</section>
4549

4650
<section class="m-4 mt-0">
@@ -50,27 +54,27 @@
5054
class="mb-1 flex w-full items-center gap-1"
5155
onsubmit={(e) => {
5256
e.preventDefault();
53-
if (newFileNameFilterInput === "") return;
57+
if (newFilePathFilterInput === "") return;
5458
// TODO error handling
55-
instance.addFileNameFilter(newFileNameFilterInput, newFileNameFilterMode);
56-
newFileNameFilterInput = "";
59+
instance.addFilePathFilter(newFilePathFilterInput, newFilePathFilterMode);
60+
newFilePathFilterInput = "";
5761
}}
5862
>
5963
<input
6064
type="text"
6165
placeholder="Enter regular expression here..."
6266
class="grow rounded-md border px-2 py-1 inset-shadow-xs ring-focus focus:outline-none focus-visible:ring-2"
63-
bind:value={newFileNameFilterInput}
67+
bind:value={newFilePathFilterInput}
6468
/>
6569
<Button.Root
6670
type="button"
67-
title="Toggle include/exclude mode (currently {newFileNameFilterMode})"
71+
title="Toggle include/exclude mode (currently {newFilePathFilterMode})"
6872
class="flex shrink-0 items-center justify-center rounded-md btn-fill-neutral p-2 text-em-med"
6973
onclick={() => {
70-
newFileNameFilterMode = newFileNameFilterMode === "exclude" ? "include" : "exclude";
74+
newFilePathFilterMode = newFilePathFilterMode === "exclude" ? "include" : "exclude";
7175
}}
7276
>
73-
{#if newFileNameFilterMode === "exclude"}
77+
{#if newFilePathFilterMode === "exclude"}
7478
<span class="aria-hidden iconify octicon--filter-remove-16"></span>
7579
{:else}
7680
<span class="aria-hidden iconify octicon--filter-16"></span>
@@ -81,7 +85,7 @@
8185
</Button.Root>
8286
</form>
8387
<ul class="h-48 overflow-y-auto rounded-md border inset-shadow-xs">
84-
{#each instance.reverseFileNameFilters as filter, i (i)}
88+
{#each instance.reverseFilePathFilters as filter, i (i)}
8589
<li class="flex gap-1 border-b px-2 py-1">
8690
<span class="grow">
8791
{filter.text}
@@ -98,14 +102,14 @@
98102
title="Delete filter"
99103
class="flex size-6 items-center justify-center rounded-sm btn-ghost-danger"
100104
onclick={() => {
101-
instance.fileNameFilters.delete(filter);
105+
instance.filePathFilters.delete(filter);
102106
}}
103107
>
104108
<span class="iconify size-4 shrink-0 place-self-center octicon--trash-16" aria-hidden="true"></span>
105109
</Button.Root>
106110
</li>
107111
{/each}
108-
{#if instance.reverseFileNameFilters.length === 0}
112+
{#if instance.reverseFilePathFilters.length === 0}
109113
<li class="flex size-full items-center justify-center text-em-med">No file path filters. Add one using the above form.</li>
110114
{/if}
111115
</ul>

web/src/lib/components/diff-filtering/index.svelte.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import type { FileDetails } from "$lib/diff-viewer.svelte";
22
import { FILE_STATUSES } from "$lib/github.svelte";
33
import { SvelteSet } from "svelte/reactivity";
44

5-
export type FileNameFilterMode = "include" | "exclude";
6-
export class FileNameFilter {
5+
export type FilePathFilterMode = "include" | "exclude";
6+
export class FilePathFilter {
77
text: string;
88
regex: RegExp;
9-
mode: FileNameFilterMode;
9+
mode: FilePathFilterMode;
1010

11-
constructor(text: string, regex: RegExp, mode: FileNameFilterMode) {
11+
constructor(text: string, regex: RegExp, mode: FilePathFilterMode) {
1212
this.text = $state(text);
1313
this.regex = $state.raw(regex);
1414
this.mode = $state(mode);
@@ -24,23 +24,25 @@ function tryCompileRegex(pattern: string): RegExp | undefined {
2424
}
2525

2626
export class DiffFilterDialogState {
27-
fileNameFilters = new SvelteSet<FileNameFilter>();
28-
reverseFileNameFilters = $derived([...this.fileNameFilters].toReversed());
27+
filePathFilters = new SvelteSet<FilePathFilter>();
28+
reverseFilePathFilters = $derived([...this.filePathFilters].toReversed());
29+
filePathInclusions = $derived(this.reverseFilePathFilters.filter((f) => f.mode === "include"));
30+
filePathExclusions = $derived(this.reverseFilePathFilters.filter((f) => f.mode === "exclude"));
2931

3032
selectedFileStatuses: string[] = $state([...FILE_STATUSES]);
3133

32-
addFileNameFilter(filterString: string, mode: FileNameFilterMode): { invalidRegex: boolean } {
34+
addFilePathFilter(filterString: string, mode: FilePathFilterMode): { invalidRegex: boolean } {
3335
const compiled = tryCompileRegex(filterString);
3436
if (!compiled) {
3537
return { invalidRegex: true };
3638
}
37-
const newFilter = new FileNameFilter(filterString, compiled, mode);
38-
this.fileNameFilters.add(newFilter);
39+
const newFilter = new FilePathFilter(filterString, compiled, mode);
40+
this.filePathFilters.add(newFilter);
3941
return { invalidRegex: false };
4042
}
4143

4244
setDefaults() {
43-
this.fileNameFilters.clear();
45+
this.filePathFilters.clear();
4446
this.selectedFileStatuses = [...FILE_STATUSES];
4547
}
4648

@@ -49,16 +51,13 @@ export class DiffFilterDialogState {
4951
if (!statusAllowed) {
5052
return false;
5153
}
52-
const pathFilterArray = [...this.fileNameFilters];
53-
const includes = pathFilterArray.filter((f) => f.mode === "include");
54-
const excludes = pathFilterArray.filter((f) => f.mode === "exclude");
55-
for (const exclude of excludes) {
54+
for (const exclude of this.filePathExclusions) {
5655
if (exclude.regex.test(file.toFile) || exclude.regex.test(file.fromFile)) {
5756
return false;
5857
}
5958
}
60-
if (includes.length > 0) {
61-
for (const include of includes) {
59+
if (this.filePathInclusions.length > 0) {
60+
for (const include of this.filePathInclusions) {
6261
if (include.regex.test(file.toFile) || include.regex.test(file.fromFile)) {
6362
return true;
6463
}

web/src/lib/components/diff/concise-diff-view.svelte.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,13 +1076,15 @@ async function getTheme(theme: BundledTheme | undefined): Promise<null | { defau
10761076

10771077
export class ConciseDiffViewCachedState {
10781078
diffViewerPatch: Promise<DiffViewerPatch>;
1079+
cacheKey: unknown;
10791080
syntaxHighlighting: boolean;
10801081
syntaxHighlightingTheme: BundledTheme | undefined;
10811082
omitPatchHeaderOnlyHunks: boolean;
10821083
wordDiffs: boolean;
10831084

10841085
constructor(diffViewerPatch: Promise<DiffViewerPatch>, props: ConciseDiffViewStateProps<unknown>) {
10851086
this.diffViewerPatch = diffViewerPatch;
1087+
this.cacheKey = props.cacheKey.current;
10861088
this.syntaxHighlighting = props.syntaxHighlighting.current;
10871089
this.syntaxHighlightingTheme = props.syntaxHighlightingTheme.current;
10881090
this.omitPatchHeaderOnlyHunks = props.omitPatchHeaderOnlyHunks.current;
@@ -1188,8 +1190,8 @@ export class ConciseDiffViewState<K> {
11881190
});
11891191

11901192
onDestroy(() => {
1191-
if (this.props.cache.current !== undefined && this.props.cacheKey.current !== undefined && this.cachedState !== undefined) {
1192-
this.props.cache.current.set(this.props.cacheKey.current, this.cachedState);
1193+
if (this.props.cache.current !== undefined && this.cachedState !== undefined) {
1194+
this.props.cache.current.set(this.cachedState.cacheKey as K, this.cachedState);
11931195
}
11941196
});
11951197
}

0 commit comments

Comments
 (0)