diff --git a/src/renderer/hooks/useNotifications.ts b/src/renderer/hooks/useNotifications.ts index 8963a83bc..827b602e7 100644 --- a/src/renderer/hooks/useNotifications.ts +++ b/src/renderer/hooks/useNotifications.ts @@ -165,6 +165,9 @@ export const useNotifications = (): UseNotificationsResult => { const notificationCount = getNotificationCount(notifications); const hasNotifications = notificationCount > 0; const hasMoreAccountNotifications = hasMoreNotifications(notifications); + const hasAnyAccountError = notifications.some( + (account) => account.error !== null, + ); const isErrorOrPaused = isError || isPaused; @@ -211,9 +214,9 @@ export const useNotifications = (): UseNotificationsResult => { .updateNotificationStatus( notificationCount, hasMoreAccountNotifications, - isErrorOrPaused, + hasAnyAccountError, ); - }, [notificationCount, hasMoreAccountNotifications, isErrorOrPaused]); + }, [notificationCount, hasMoreAccountNotifications, hasAnyAccountError]); const refetchNotifications = useCallback(async () => { await refetch(); diff --git a/src/renderer/stores/defaults.ts b/src/renderer/stores/defaults.ts index c83ab06ff..f8b5e2ab4 100644 --- a/src/renderer/stores/defaults.ts +++ b/src/renderer/stores/defaults.ts @@ -40,7 +40,7 @@ export const DEFAULT_FILTERS_STATE: FiltersState = { export const DEFAULT_RUNTIME_STATE = { notificationCount: 0, hasMoreAccountNotifications: false, - isError: false, + hasAnyAccountError: false, isOnline: true, }; diff --git a/src/renderer/stores/subscriptions.test.ts b/src/renderer/stores/subscriptions.test.ts index 46ef75798..d203b5feb 100644 --- a/src/renderer/stores/subscriptions.test.ts +++ b/src/renderer/stores/subscriptions.test.ts @@ -203,7 +203,7 @@ describe('renderer/stores/subscriptions.ts', () => { expect(tray.setTrayIconColorAndTitle).toHaveBeenCalledTimes(1); }); - it('should trigger setTrayIconColorAndTitle when isError changes', () => { + it('should trigger setTrayIconColorAndTitle when hasAnyAccountError changes', () => { useRuntimeStore.getState().updateNotificationStatus(0, false, true); expect(tray.setTrayIconColorAndTitle).toHaveBeenCalledTimes(1); diff --git a/src/renderer/stores/subscriptions.ts b/src/renderer/stores/subscriptions.ts index 5b07292d2..a29509fee 100644 --- a/src/renderer/stores/subscriptions.ts +++ b/src/renderer/stores/subscriptions.ts @@ -154,7 +154,7 @@ export function initializeStoreSubscriptions(): () => void { (state) => ({ notificationCount: state.notificationCount, hasMoreAccountNotifications: state.hasMoreAccountNotifications, - isError: state.isError, + hasAnyAccountError: state.hasAnyAccountError, isOnline: state.isOnline, }), setTrayIconColorAndTitle, diff --git a/src/renderer/stores/types.ts b/src/renderer/stores/types.ts index a1892f96d..a36e66ba7 100644 --- a/src/renderer/stores/types.ts +++ b/src/renderer/stores/types.ts @@ -308,7 +308,7 @@ export type SettingsStore = SettingsState & SettingsActions; export interface RuntimeState { notificationCount: number; hasMoreAccountNotifications: boolean; - isError: boolean; + hasAnyAccountError: boolean; isOnline: boolean; } @@ -322,7 +322,7 @@ export interface RuntimeActions { updateNotificationStatus: ( notificationCount: number, hasMoreAccountNotifications: boolean, - isError: boolean, + hasAnyAccountError: boolean, ) => void; /** diff --git a/src/renderer/stores/useRuntimeStore.test.ts b/src/renderer/stores/useRuntimeStore.test.ts index f7f1bc3ca..ce5218473 100644 --- a/src/renderer/stores/useRuntimeStore.test.ts +++ b/src/renderer/stores/useRuntimeStore.test.ts @@ -5,31 +5,34 @@ describe('renderer/stores/useRuntimeStore.ts', () => { const { notificationCount, hasMoreAccountNotifications, - isError, + hasAnyAccountError, isOnline, } = useRuntimeStore.getState(); expect(notificationCount).toBe(0); expect(hasMoreAccountNotifications).toBe(false); - expect(isError).toBe(false); + expect(hasAnyAccountError).toBe(false); expect(isOnline).toBe(true); }); it('should update notification status', () => { - useRuntimeStore.getState().updateNotificationStatus(10, true, false); + useRuntimeStore.getState().updateNotificationStatus(10, true, true); - const { notificationCount, hasMoreAccountNotifications, isError } = - useRuntimeStore.getState(); + const { + notificationCount, + hasMoreAccountNotifications, + hasAnyAccountError, + } = useRuntimeStore.getState(); expect(notificationCount).toBe(10); expect(hasMoreAccountNotifications).toBe(true); - expect(isError).toBe(false); + expect(hasAnyAccountError).toBe(true); }); - it('should reflect error state', () => { + it('should reflect hasAnyAccountError state', () => { useRuntimeStore.getState().updateNotificationStatus(0, false, true); - expect(useRuntimeStore.getState().isError).toBe(true); + expect(useRuntimeStore.getState().hasAnyAccountError).toBe(true); }); it('should update online status', () => { diff --git a/src/renderer/stores/useRuntimeStore.ts b/src/renderer/stores/useRuntimeStore.ts index 76eb77233..9b68ae885 100644 --- a/src/renderer/stores/useRuntimeStore.ts +++ b/src/renderer/stores/useRuntimeStore.ts @@ -19,13 +19,17 @@ const useRuntimeStore = create()( subscribeWithSelector((set) => ({ ...DEFAULT_RUNTIME_STATE, - /** Updates the notification count, hasMore flag, and error flag from the latest fetch result. */ + /** Updates the notification count, hasMore flag, and account error flag from the latest fetch result. */ updateNotificationStatus: ( notificationCount: number, hasMoreAccountNotifications: boolean, - isError: boolean, + hasAnyAccountError: boolean, ) => { - set({ notificationCount, hasMoreAccountNotifications, isError }); + set({ + notificationCount, + hasMoreAccountNotifications, + hasAnyAccountError, + }); }, /** Updates the online/offline connectivity status. */ diff --git a/src/renderer/utils/system/tray.test.ts b/src/renderer/utils/system/tray.test.ts index 7dfe1b788..ad4e33af2 100644 --- a/src/renderer/utils/system/tray.test.ts +++ b/src/renderer/utils/system/tray.test.ts @@ -11,7 +11,7 @@ describe('renderer/utils/system/tray.ts', () => { useRuntimeStore.setState({ notificationCount: 0, hasMoreAccountNotifications: false, - isError: false, + hasAnyAccountError: false, isOnline: true, }); useSettingsStore.setState({ @@ -121,8 +121,8 @@ describe('renderer/utils/system/tray.ts', () => { ); }); - it('should pass appState error when isError is true', () => { - useRuntimeStore.setState({ isError: true }); + it('should pass appState error when any account has an error', () => { + useRuntimeStore.setState({ hasAnyAccountError: true }); setTrayIconColorAndTitle(); @@ -135,8 +135,8 @@ describe('renderer/utils/system/tray.ts', () => { expect(updateTrayTitleSpy).toHaveBeenCalledWith(''); }); - it('should pass appState offline (not error) when both isError and isOnline are false', () => { - useRuntimeStore.setState({ isError: true, isOnline: false }); + it('should pass appState offline (not error) when both hasAnyAccountError and isOnline are false', () => { + useRuntimeStore.setState({ hasAnyAccountError: true, isOnline: false }); setTrayIconColorAndTitle(); diff --git a/src/renderer/utils/system/tray.ts b/src/renderer/utils/system/tray.ts index 8ed6d97ec..cfa19153c 100644 --- a/src/renderer/utils/system/tray.ts +++ b/src/renderer/utils/system/tray.ts @@ -12,7 +12,7 @@ import { updateTrayColor, updateTrayTitle } from './comms'; * Updates the tray icon and title using the current notification status, * online status, and settings store values. * - * Notification status (count, hasMore, isError) is read from useRuntimeStore, + * Notification status (count, hasMore, hasAnyAccountError) is read from useRuntimeStore, * which is kept up-to-date by useNotifications with already-filtered values. * This avoids re-applying filter logic against the raw query cache. * @@ -20,8 +20,12 @@ import { updateTrayColor, updateTrayTitle } from './comms'; * whether triggered by a notification fetch, a settings change, or an online/offline event. */ export function setTrayIconColorAndTitle() { - const { notificationCount, hasMoreAccountNotifications, isError, isOnline } = - useRuntimeStore.getState(); + const { + notificationCount, + hasMoreAccountNotifications, + hasAnyAccountError, + isOnline, + } = useRuntimeStore.getState(); const { showNotificationsCountInTray, useUnreadActiveIcon, @@ -31,7 +35,7 @@ export function setTrayIconColorAndTitle() { let title = ''; if ( isOnline && - !isError && + !hasAnyAccountError && notificationCount > 0 && showNotificationsCountInTray ) { @@ -40,7 +44,7 @@ export function setTrayIconColorAndTitle() { const appState: TrayAppState = !isOnline ? 'offline' - : isError + : hasAnyAccountError ? 'error' : 'online';