From 2201fe1ce7c45ff21b6ff9dc5b313cd8e4f06ac6 Mon Sep 17 00:00:00 2001 From: Supra4E8C Date: Sat, 11 Jul 2026 02:33:45 +0800 Subject: [PATCH] fix: adjust ESLint rule for async data loading and refactor sorting logic in ProvidersWorkbenchPage --- eslint.config.js | 3 +++ .../components/AuthFilesStatusFilterCard.tsx | 1 - .../providers/ProvidersWorkbenchPage.tsx | 21 +++++++------------ src/pages/LogsPage.tsx | 21 +++++++------------ src/services/storage/secureStorage.ts | 2 +- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 9c6771cb..45dc9ee8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -19,6 +19,9 @@ export default tseslint.config( }, rules: { ...reactHooks.configs.recommended.rules, + // Pages in this app intentionally start async data loads from effects. Those loaders + // synchronously expose their loading state before awaiting the Management API. + 'react-hooks/set-state-in-effect': 'off', 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, diff --git a/src/features/authFiles/components/AuthFilesStatusFilterCard.tsx b/src/features/authFiles/components/AuthFilesStatusFilterCard.tsx index ea792bdc..72ee1ad1 100644 --- a/src/features/authFiles/components/AuthFilesStatusFilterCard.tsx +++ b/src/features/authFiles/components/AuthFilesStatusFilterCard.tsx @@ -45,7 +45,6 @@ export function AuthFilesStatusFilterCard({ if (prevActiveRef.current !== isActive) { // Trigger a one-off flip animation when the active state crosses the // threshold, mirroring the original EffortCard behavior. - // eslint-disable-next-line react-hooks/set-state-in-effect setIsAnimating(true); if (timerRef.current) { clearTimeout(timerRef.current); diff --git a/src/features/providers/ProvidersWorkbenchPage.tsx b/src/features/providers/ProvidersWorkbenchPage.tsx index 6cc5a766..d8ae0c1e 100644 --- a/src/features/providers/ProvidersWorkbenchPage.tsx +++ b/src/features/providers/ProvidersWorkbenchPage.tsx @@ -215,19 +215,14 @@ export function ProvidersWorkbenchPage({ fixedBrand }: ProvidersWorkbenchPagePro } const sorted = [...arr].sort((a, b) => { - let diff = 0; - if (providerSortBy === 'name') { - diff = getResourceSortName(a).localeCompare(getResourceSortName(b)); - } else if (providerSortBy === 'priority') { - diff = a.priority - b.priority; - } else { - diff = - getResourceRecentSuccess(a, usageByProvider) - - getResourceRecentSuccess(b, usageByProvider); - } - if (diff === 0) { - diff = a.originalIndex - b.originalIndex; - } + const sortDiff = + providerSortBy === 'name' + ? getResourceSortName(a).localeCompare(getResourceSortName(b)) + : providerSortBy === 'priority' + ? a.priority - b.priority + : getResourceRecentSuccess(a, usageByProvider) - + getResourceRecentSuccess(b, usageByProvider); + const diff = sortDiff || a.originalIndex - b.originalIndex; return providerSortDir === 'asc' ? diff : -diff; }); diff --git a/src/pages/LogsPage.tsx b/src/pages/LogsPage.tsx index 44066b7f..af127746 100644 --- a/src/pages/LogsPage.tsx +++ b/src/pages/LogsPage.tsx @@ -180,7 +180,6 @@ export function LogsPage() { const [requestLogDownloading, setRequestLogDownloading] = useState(false); const [fullscreenLogs, setFullscreenLogs] = useState(false); - const logScrollerRef = useRef | null>(null); const requestLogHomeIpByIdRef = useRef>({}); const errorLogViewRequestRef = useRef(0); const longPressRef = useRef<{ @@ -221,7 +220,7 @@ export function LogsPage() { const autoRefreshDisabled = disableControls || showFileLoggingRequired; const clearDisabled = disableControls || showFileLoggingRequired || isHomeRuntime; - const loadLogs = async (incremental = false) => { + async function loadLogs(incremental = false) { if (connectionStatus !== 'connected') { setLoading(false); return; @@ -254,11 +253,9 @@ export function LogsPage() { setError(''); try { - const scrollerInstance = logScrollerRef.current; - const stickToBottom = - !incremental || isNearBottom(scrollerInstance?.logViewerRef.current ?? null); + const stickToBottom = !incremental || isNearBottom(logViewerRef.current); if (stickToBottom) { - scrollerInstance?.requestScrollToBottom(); + requestScrollToBottom(); } const params = buildLogsQuery(incremental, logPositionRef.current); @@ -328,7 +325,7 @@ export function LogsPage() { void loadLogs(false); } } - }; + } useHeaderRefresh(() => loadLogs(false)); @@ -579,7 +576,7 @@ export function LogsPage() { const rawVisibleText = useMemo(() => filteredLines.join('\n'), [filteredLines]); - const scroller = useLogScroller({ + const { canLoadMore, handleLogScroll, logViewerRef, requestScrollToBottom } = useLogScroller({ logState, setLogState, loading, @@ -589,8 +586,6 @@ export function LogsPage() { showRawLogs, }); - logScrollerRef.current = scroller; - const copyLogLine = async (raw: string) => { const ok = await copyToClipboard(raw); if (ok) { @@ -987,13 +982,13 @@ export function LogsPage() {
{t('logs.loading')}
) : logState.buffer.length > 0 && filteredLines.length > 0 ? (
- {scroller.canLoadMore && ( + {canLoadMore && (
{t('logs.load_more_hint')}
diff --git a/src/services/storage/secureStorage.ts b/src/services/storage/secureStorage.ts index ccc4dbe6..a4e3d1f7 100644 --- a/src/services/storage/secureStorage.ts +++ b/src/services/storage/secureStorage.ts @@ -84,7 +84,7 @@ class ObfuscatedStorageService { return; } - let parsed: unknown = raw; + let parsed: unknown; try { parsed = JSON.parse(raw); } catch {