diff --git a/src/pages/audit.tsx b/src/pages/audit.tsx
index 4c32f7b..cc1e7fe 100644
--- a/src/pages/audit.tsx
+++ b/src/pages/audit.tsx
@@ -343,7 +343,7 @@ export default function AuditPage() {
>
{loading ? "Auditing..." : "Run Audit"}
diff --git a/src/pages/extensions.tsx b/src/pages/extensions.tsx
index 99827cc..4ea7c52 100644
--- a/src/pages/extensions.tsx
+++ b/src/pages/extensions.tsx
@@ -86,9 +86,9 @@ export default function ExtensionsPage() {
const groups = allGrouped();
const match = groupKeyParam
? groups.find((g) => g.groupKey === groupKeyParam)
- : groups.find(
- (g) => g.name.toLowerCase() === nameParam!.toLowerCase(),
- );
+ : nameParam
+ ? groups.find((g) => g.name.toLowerCase() === nameParam.toLowerCase())
+ : undefined;
if (match) {
setSelectedId(match.groupKey);
setScrollToId(match.groupKey);
@@ -196,7 +196,7 @@ export default function ExtensionsPage() {
>
{checkingUpdates ? "Checking..." : "Check Updates"}
diff --git a/src/pages/overview.tsx b/src/pages/overview.tsx
index d25600a..992c734 100644
--- a/src/pages/overview.tsx
+++ b/src/pages/overview.tsx
@@ -134,7 +134,7 @@ function QuickAction({
className={
loading
? Icon === RefreshCw
- ? "animate-spin"
+ ? "origin-center animate-spin"
: "animate-scanning"
: ""
}
diff --git a/src/pages/settings.tsx b/src/pages/settings.tsx
index 5dc7826..082c0f6 100644
--- a/src/pages/settings.tsx
+++ b/src/pages/settings.tsx
@@ -93,11 +93,10 @@ function UpdateSection() {
disabled={checking}
className="flex items-center gap-1.5 rounded-lg border border-border px-2.5 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-50 transition-colors"
>
- {checking ? (
-
- ) : (
-
- )}
+
{checking ? "Checking..." : "Check for Updates"}
)}
@@ -135,11 +134,10 @@ function WebUpdateSection() {
disabled={checking}
className="flex items-center gap-1.5 rounded-lg border border-border px-2.5 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-50 transition-colors"
>
- {checking ? (
-
- ) : (
-
- )}
+
{checking ? "Checking..." : "Check for Updates"}
)}
diff --git a/src/stores/audit-store.ts b/src/stores/audit-store.ts
index 7959a6a..bc978b3 100644
--- a/src/stores/audit-store.ts
+++ b/src/stores/audit-store.ts
@@ -4,6 +4,8 @@ import type { AuditResult, TrustTier } from "@/lib/types";
import { useExtensionStore } from "@/stores/extension-store";
import { toast } from "@/stores/toast-store";
+const MIN_AUDIT_LOADING_VISIBLE_MS = 600;
+
interface AuditState {
results: AuditResult[];
loading: boolean;
@@ -31,18 +33,24 @@ export const useAuditStore = create((set) => ({
}
},
async runAudit() {
+ const startedAt = Date.now();
set({ loading: true });
// Yield to let the browser paint loading state before Tauri IPC call
await new Promise((r) => setTimeout(r, 50));
try {
const results = await api.runAudit();
- set({ results, loading: false });
+ set({ results });
// Refresh extensions so trust_score updates in the Extensions page
useExtensionStore.getState().fetch();
toast.success("Audit complete");
} catch {
- set({ loading: false });
toast.error("Audit failed");
+ } finally {
+ const remaining = MIN_AUDIT_LOADING_VISIBLE_MS - (Date.now() - startedAt);
+ if (remaining > 0) {
+ await new Promise((resolve) => setTimeout(resolve, remaining));
+ }
+ set({ loading: false });
}
},
}));
diff --git a/src/stores/extension-store.ts b/src/stores/extension-store.ts
index 85c1f45..0013ce0 100644
--- a/src/stores/extension-store.ts
+++ b/src/stores/extension-store.ts
@@ -19,6 +19,8 @@ import { toast } from "./toast-store";
export { buildGroups } from "./extension-helpers";
+const MIN_CHECK_UPDATES_VISIBLE_MS = 600;
+
interface PendingDelete {
ids: Set;
extensions: Extension[];
@@ -338,6 +340,7 @@ export const useExtensionStore = create((set, get) => ({
},
async checkUpdates() {
+ const startedAt = Date.now();
set({ checkingUpdates: true });
try {
const result = await api.checkUpdates();
@@ -347,6 +350,10 @@ export const useExtensionStore = create((set, get) => ({
}
set({ updateStatuses: map, newRepoSkills: result.new_skills });
} finally {
+ const remaining = MIN_CHECK_UPDATES_VISIBLE_MS - (Date.now() - startedAt);
+ if (remaining > 0) {
+ await new Promise((resolve) => setTimeout(resolve, remaining));
+ }
set({ checkingUpdates: false });
}
},
diff --git a/src/stores/update-store.ts b/src/stores/update-store.ts
index 039df87..7cf5ea7 100644
--- a/src/stores/update-store.ts
+++ b/src/stores/update-store.ts
@@ -36,6 +36,8 @@ export function cleanChangelog(body: string): string {
* Shared between desktop and web update flows so a dismissal in either mode silences both. */
export const DISMISS_KEY_PREFIX = "hk-update-dismissed-v";
+const MIN_UPDATE_CHECK_VISIBLE_MS = 600;
+
interface UpdateState {
/** Available update version, null if none or not checked yet */
available: { version: string; body: string } | null;
@@ -66,6 +68,7 @@ export const useUpdateStore = create((set, get) => ({
async checkForUpdate() {
if (get().checking) return;
+ const startedAt = Date.now();
set({ checking: true });
try {
const update = await check();
@@ -84,6 +87,10 @@ export const useUpdateStore = create((set, get) => ({
} catch {
// Silent failure — update check is non-critical
} finally {
+ const remaining = MIN_UPDATE_CHECK_VISIBLE_MS - (Date.now() - startedAt);
+ if (remaining > 0) {
+ await new Promise((resolve) => setTimeout(resolve, remaining));
+ }
set({ checking: false });
}
},
diff --git a/src/stores/web-update-store.ts b/src/stores/web-update-store.ts
index e99a766..d6d0b27 100644
--- a/src/stores/web-update-store.ts
+++ b/src/stores/web-update-store.ts
@@ -5,6 +5,7 @@ const RELEASES_URL =
"https://api.github.com/repos/RealZST/HarnessKit/releases/latest";
const CACHE_KEY = "hk-web-update-cache";
const CACHE_TTL_MS = 60 * 60 * 1000;
+const MIN_UPDATE_CHECK_VISIBLE_MS = 600;
interface CachedRelease {
tag: string;
@@ -100,6 +101,7 @@ export const useWebUpdateStore = create((set, get) => ({
async checkForUpdate(force = false) {
if (get().checking) return;
+ const startedAt = Date.now();
set({ checking: true });
try {
const release = await fetchLatestRelease(force);
@@ -113,6 +115,10 @@ export const useWebUpdateStore = create((set, get) => ({
dismissed,
});
} finally {
+ const remaining = MIN_UPDATE_CHECK_VISIBLE_MS - (Date.now() - startedAt);
+ if (remaining > 0) {
+ await new Promise((resolve) => setTimeout(resolve, remaining));
+ }
set({ checking: false });
}
},