mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
indexing progressbar fixes
This commit is contained in:
@@ -402,40 +402,6 @@
|
|||||||
{@render Shortcut({ text: 'Select', keybind: ['↵']})}
|
{@render Shortcut({ text: 'Select', keybind: ['↵']})}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</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>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import browser from "webextension-polyfill";
|
|||||||
export function mountSearchBar(
|
export function mountSearchBar(
|
||||||
titleElement: Element,
|
titleElement: Element,
|
||||||
api: any,
|
api: any,
|
||||||
appRef: { current: any; storageChangeHandler?: any },
|
appRef: { current: any; storageChangeHandler?: any; progressHandler?: any },
|
||||||
) {
|
) {
|
||||||
if (titleElement.querySelector(".search-trigger")) {
|
if (titleElement.querySelector(".search-trigger")) {
|
||||||
return;
|
return;
|
||||||
@@ -21,6 +21,72 @@ export function mountSearchBar(
|
|||||||
const searchButton = document.createElement("div");
|
const searchButton = document.createElement("div");
|
||||||
searchButton.className = "search-trigger";
|
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 = () => {
|
const updateSearchButtonDisplay = () => {
|
||||||
searchButton.innerHTML = /* html */ `
|
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">
|
<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();
|
updateSearchButtonDisplay();
|
||||||
titleElement.appendChild(searchButton);
|
titleElement.appendChild(searchButton);
|
||||||
|
titleElement.appendChild(progressContainer);
|
||||||
|
|
||||||
// Listen for hotkey setting changes
|
// Listen for hotkey setting changes
|
||||||
const handleStorageChange = (changes: any, area: string) => {
|
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) {
|
if (appRef.current) {
|
||||||
try {
|
try {
|
||||||
unmount(appRef.current);
|
unmount(appRef.current);
|
||||||
@@ -82,11 +149,23 @@ 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
|
// Remove search trigger button
|
||||||
const searchTrigger = document.querySelector(".search-trigger");
|
const searchTrigger = document.querySelector(".search-trigger");
|
||||||
if (searchTrigger) {
|
if (searchTrigger) {
|
||||||
searchTrigger.remove();
|
searchTrigger.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove progress container
|
||||||
|
const progressContainer = document.querySelector(".search-progress-container");
|
||||||
|
if (progressContainer) {
|
||||||
|
progressContainer.remove();
|
||||||
|
}
|
||||||
|
|
||||||
// Remove search root
|
// Remove search root
|
||||||
const searchRoot = document.querySelector("div[data-search-root]");
|
const searchRoot = document.querySelector("div[data-search-root]");
|
||||||
|
|||||||
@@ -81,4 +81,53 @@
|
|||||||
|
|
||||||
.animate-shimmer {
|
.animate-shimmer {
|
||||||
animation: shimmer 2s infinite;
|
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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user