Skip to content

Commit 9c0a3c3

Browse files
committed
File viewer: search progress bar, spinner, stop
- Accent-colored progress bar at bottom of search bar during scan - Inline spinner next to status text while searching - Stop button (■) keeps results but cancels background scan - Esc stops scan first, closes search bar second - Partial results labeled "(partial)" after match count - Respects prefers-reduced-motion
1 parent 86ef2a5 commit 9c0a3c3

1 file changed

Lines changed: 71 additions & 8 deletions

File tree

apps/desktop/src/routes/viewer/+page.svelte

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,14 @@
399399
searchStatus = 'idle'
400400
}
401401
402+
/** Stops the background scan but keeps accumulated matches for browsing. */
403+
function stopSearch() {
404+
stopSearchPoll()
405+
if (!sessionId) return
406+
viewerSearchCancel(sessionId).catch(() => {})
407+
searchStatus = 'cancelled'
408+
}
409+
402410
// Indexing status polling functions
403411
function startIndexingPoll() {
404412
stopIndexingPoll()
@@ -620,7 +628,11 @@
620628
windowReady,
621629
})
622630
if (searchVisible) {
623-
closeSearch()
631+
if (searchStatus === 'running') {
632+
stopSearch()
633+
} else {
634+
closeSearch()
635+
}
624636
} else {
625637
closeWindow()
626638
}
@@ -853,17 +865,28 @@
853865
spellcheck="false"
854866
/>
855867
<span class="match-count" aria-live="polite">
856-
{#if searchMatches.length > 0}
868+
{#if searchStatus === 'running'}
869+
<span class="spinner spinner-sm search-spinner" aria-hidden="true"></span>
870+
{#if searchMatches.length > 0}
871+
{currentMatchIndex + 1} of {searchMatches.length}{searchLimitReached ? '+' : ''}
872+
&middot; {Math.round(searchProgress * 100)}%
873+
{:else}
874+
Searching... {Math.round(searchProgress * 100)}%
875+
{/if}
876+
{:else if searchMatches.length > 0}
857877
{currentMatchIndex + 1} of {searchMatches.length}{searchLimitReached ? '+' : ''}
858-
{#if searchStatus === 'running'}
859-
({Math.round(searchProgress * 100)}%)
878+
{#if searchStatus === 'cancelled'}
879+
(partial)
860880
{/if}
861-
{:else if searchStatus === 'running'}
862-
Searching... {Math.round(searchProgress * 100)}%
863-
{:else if searchQuery && searchStatus === 'done'}
864-
No matches
881+
{:else if searchQuery && (searchStatus === 'done' || searchStatus === 'cancelled')}
882+
No matches{searchStatus === 'cancelled' ? ' (partial)' : ''}
865883
{/if}
866884
</span>
885+
{#if searchStatus === 'running'}
886+
<button onclick={stopSearch} aria-label="Stop searching" use:tooltip={'Stop scanning and keep results'}
887+
>&#x25A0;</button
888+
>
889+
{/if}
867890
<button
868891
onclick={findPrev}
869892
disabled={searchMatches.length === 0}
@@ -879,6 +902,17 @@
879902
<button onclick={closeSearch} aria-label="Close search" use:tooltip={{ text: 'Close', shortcut: 'Esc' }}
880903
>&#x2715;</button
881904
>
905+
{#if searchStatus === 'running'}
906+
<div
907+
class="search-progress"
908+
role="progressbar"
909+
aria-valuenow={Math.round(searchProgress * 100)}
910+
aria-valuemin={0}
911+
aria-valuemax={100}
912+
>
913+
<div class="search-progress-fill" style="width: {searchProgress * 100}%"></div>
914+
</div>
915+
{/if}
882916
</div>
883917
{/if}
884918

@@ -973,6 +1007,7 @@
9731007
}
9741008
9751009
.search-bar {
1010+
position: relative;
9761011
display: flex;
9771012
align-items: center;
9781013
gap: var(--spacing-xs);
@@ -1003,6 +1038,34 @@
10031038
font-size: var(--font-size-sm);
10041039
color: var(--color-text-secondary);
10051040
min-width: 70px;
1041+
white-space: nowrap;
1042+
}
1043+
1044+
.search-spinner {
1045+
vertical-align: text-bottom;
1046+
margin-right: 2px;
1047+
}
1048+
1049+
.search-progress {
1050+
position: absolute;
1051+
bottom: 0;
1052+
left: 0;
1053+
right: 0;
1054+
height: 2px;
1055+
background: var(--color-bg-tertiary);
1056+
overflow: hidden;
1057+
}
1058+
1059+
.search-progress-fill {
1060+
height: 100%;
1061+
background: var(--color-accent);
1062+
transition: width var(--transition-base);
1063+
}
1064+
1065+
@media (prefers-reduced-motion: reduce) {
1066+
.search-progress-fill {
1067+
transition: none;
1068+
}
10061069
}
10071070
10081071
.search-bar button {

0 commit comments

Comments
 (0)