indexing progressbar fixes

This commit is contained in:
StroepWafel
2026-01-22 19:05:25 +10:30
parent 89fd9bbd89
commit 07ff6d25ca
3 changed files with 130 additions and 36 deletions
@@ -402,40 +402,6 @@
{@render Shortcut({ text: 'Select', keybind: ['↵']})}
{/if}
</div>
{#if isIndexing}
<div class="inset-x-0 top-0">
<div class="absolute right-2 -bottom-6 flex items-center gap-2 text-[10px] text-zinc-500 dark:text-zinc-400">
<span class="font-medium flex items-center gap-1">
<svg class="animate-spin h-3 w-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Indexing
</span>
{#if totalJobs > 0}
<span class="text-zinc-400 dark:text-zinc-500 font-mono">
{completedJobs}/{totalJobs}
</span>
<span class="text-zinc-400 dark:text-zinc-500 font-mono">
{Math.round((completedJobs / totalJobs) * 100)}%
</span>
{/if}
</div>
<div class="overflow-hidden h-1.5 bg-zinc-200 dark:bg-zinc-700 rounded-full shadow-inner">
<div
class="h-full bg-gradient-to-r from-blue-500 via-blue-600 to-blue-500 transition-all duration-300 ease-out rounded-full relative overflow-hidden"
style="width: {totalJobs > 0 ? Math.max(2, (completedJobs / totalJobs) * 100) : 0}%"
>
<div class="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-shimmer"></div>
</div>
</div>
{#if indexingStatus || indexingDetail}
<div class="absolute right-2 -bottom-10 text-[9px] text-zinc-400 dark:text-zinc-500 max-w-[250px] truncate" title={indexingStatus || indexingDetail}>
{indexingStatus || indexingDetail}
</div>
{/if}
</div>
{/if}
</div>
{/if}
</div>
@@ -8,7 +8,7 @@ import browser from "webextension-polyfill";
export function mountSearchBar(
titleElement: Element,
api: any,
appRef: { current: any; storageChangeHandler?: any },
appRef: { current: any; storageChangeHandler?: any; progressHandler?: any },
) {
if (titleElement.querySelector(".search-trigger")) {
return;
@@ -21,6 +21,72 @@ export function mountSearchBar(
const searchButton = document.createElement("div");
searchButton.className = "search-trigger";
// Create progress indicator container
const progressContainer = document.createElement("div");
progressContainer.className = "search-progress-container";
progressContainer.style.cssText = "display: flex; align-items: center; gap: 8px; margin-left: 8px; min-width: 120px;";
// Create progress bar
const progressBarWrapper = document.createElement("div");
progressBarWrapper.className = "search-progress-bar-wrapper";
progressBarWrapper.style.cssText = "flex: 1; height: 4px; background: rgba(0, 0, 0, 0.1); border-radius: 2px; overflow: hidden; display: none;";
const progressBar = document.createElement("div");
progressBar.className = "search-progress-bar";
progressBar.style.cssText = "height: 100%; background: linear-gradient(90deg, #3b82f6, #2563eb, #3b82f6); transition: width 0.3s ease-out; width: 0%; position: relative;";
// Add shimmer effect
const shimmer = document.createElement("div");
shimmer.style.cssText = "position: absolute; inset: 0; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); animation: shimmer 2s infinite;";
progressBar.appendChild(shimmer);
progressBarWrapper.appendChild(progressBar);
// Create progress text
const progressText = document.createElement("span");
progressText.className = "search-progress-text";
progressText.style.cssText = "font-size: 11px; color: #666; white-space: nowrap; display: none;";
progressContainer.appendChild(progressBarWrapper);
progressContainer.appendChild(progressText);
// Indexing state
let isIndexing = false;
let completedJobs = 0;
let totalJobs = 0;
let indexingStatus: string | null = null;
const updateProgressDisplay = () => {
if (isIndexing && totalJobs > 0) {
const percentage = Math.round((completedJobs / totalJobs) * 100);
progressBar.style.width = `${Math.max(2, percentage)}%`;
progressBarWrapper.style.display = "block";
if (indexingStatus) {
progressText.textContent = indexingStatus.length > 20 ? indexingStatus.substring(0, 20) + "..." : indexingStatus;
progressText.style.display = "block";
} else {
progressText.textContent = `${completedJobs}/${totalJobs} (${percentage}%)`;
progressText.style.display = "block";
}
} else {
progressBarWrapper.style.display = "none";
progressText.style.display = "none";
}
};
// Listen for indexing progress events
const progressHandler = (event: CustomEvent) => {
const { completed, total, indexing, status } = event.detail;
completedJobs = completed || 0;
totalJobs = total || 0;
isIndexing = indexing || false;
indexingStatus = status || null;
updateProgressDisplay();
};
window.addEventListener('indexing-progress', progressHandler as EventListener);
appRef.progressHandler = progressHandler;
const updateSearchButtonDisplay = () => {
searchButton.innerHTML = /* html */ `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -34,6 +100,7 @@ export function mountSearchBar(
updateSearchButtonDisplay();
titleElement.appendChild(searchButton);
titleElement.appendChild(progressContainer);
// Listen for hotkey setting changes
const handleStorageChange = (changes: any, area: string) => {
@@ -72,7 +139,7 @@ export function mountSearchBar(
}
}
export function cleanupSearchBar(appRef: { current: any; storageChangeHandler?: any }) {
export function cleanupSearchBar(appRef: { current: any; storageChangeHandler?: any; progressHandler?: any }) {
if (appRef.current) {
try {
unmount(appRef.current);
@@ -82,12 +149,24 @@ export function cleanupSearchBar(appRef: { current: any; storageChangeHandler?:
}
}
// Remove progress event listener
if (appRef.progressHandler) {
window.removeEventListener('indexing-progress', appRef.progressHandler as EventListener);
appRef.progressHandler = null;
}
// Remove search trigger button
const searchTrigger = document.querySelector(".search-trigger");
if (searchTrigger) {
searchTrigger.remove();
}
// Remove progress container
const progressContainer = document.querySelector(".search-progress-container");
if (progressContainer) {
progressContainer.remove();
}
// Remove search root
const searchRoot = document.querySelector("div[data-search-root]");
if (searchRoot) {
@@ -82,3 +82,52 @@
.animate-shimmer {
animation: shimmer 2s infinite;
}
/* Progress indicator next to search trigger */
.search-progress-container {
display: flex;
align-items: center;
gap: 8px;
margin-left: 8px;
min-width: 120px;
}
.search-progress-bar-wrapper {
flex: 1;
height: 4px;
background: rgba(0, 0, 0, 0.1);
border-radius: 2px;
overflow: hidden;
display: none;
}
.dark .search-progress-bar-wrapper {
background: rgba(255, 255, 255, 0.1);
}
.search-progress-bar {
height: 100%;
background: linear-gradient(90deg, #3b82f6, #2563eb, #3b82f6);
transition: width 0.3s ease-out;
width: 0%;
position: relative;
}
.search-progress-bar::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
animation: shimmer 2s infinite;
}
.search-progress-text {
font-size: 11px;
color: #666;
white-space: nowrap;
display: none;
}
.dark .search-progress-text {
color: #999;
}