diff --git a/src/renderer/__mocks__/state-mocks.ts b/src/renderer/__mocks__/state-mocks.ts index 7a192bb22..65acbd6ae 100644 --- a/src/renderer/__mocks__/state-mocks.ts +++ b/src/renderer/__mocks__/state-mocks.ts @@ -1,8 +1,8 @@ import { Constants } from '../constants'; import { + type Account, type AppearanceSettingsState, - type AuthState, FetchType, GroupBy, type KeyboardAcceleratorShortcut, @@ -18,7 +18,7 @@ import { import { mockGitHubCloudAccount, mockGitHubEnterpriseServerAccount } from './account-mocks'; -export const mockAuth: AuthState = { +export const mockAuth: { accounts: Account[] } = { accounts: [mockGitHubCloudAccount, mockGitHubEnterpriseServerAccount], }; diff --git a/src/renderer/hooks/useLogins.test.tsx b/src/renderer/hooks/useLogins.test.tsx index c0607889d..6addeeca5 100644 --- a/src/renderer/hooks/useLogins.test.tsx +++ b/src/renderer/hooks/useLogins.test.tsx @@ -10,10 +10,9 @@ import { Constants } from '../constants'; import { useAccountsStore } from '../stores'; -import type { AuthState, ClientID, ClientSecret, Token } from '../types'; +import type { ClientID, ClientSecret, Token } from '../types'; import type { DeviceFlowSession } from '../utils/auth/types'; -import * as authUtils from '../utils/auth/utils'; import { getAdapter } from '../utils/forges/registry'; import { useLogins } from './useLogins'; @@ -36,19 +35,20 @@ const renderLoginsHook = () => renderHook(() => useLogins(), { wrapper: createWr describe('renderer/hooks/useLogins.ts', () => { const removeAccountNotificationsMock = vi.fn(); + let createAccountSpy: ReturnType; + let removeAccountSpy: ReturnType; beforeEach(() => { removeAccountNotificationsMock.mockReset(); setNotificationsOverrides({ removeAccountNotifications: removeAccountNotificationsMock }); - }); - const addAccountSpy = vi - .spyOn(authUtils, 'addAccount') - .mockImplementation(vi.fn()) - .mockResolvedValueOnce({ - accounts: [mockGitHubCloudAccount], - } as unknown as AuthState); - const removeAccountSpy = vi.spyOn(authUtils, 'removeAccount'); + createAccountSpy = vi + .spyOn(useAccountsStore.getState(), 'createAccount') + .mockResolvedValue(undefined); + createAccountSpy.mockClear(); + removeAccountSpy = vi.spyOn(useAccountsStore.getState(), 'removeAccount'); + removeAccountSpy.mockClear(); + }); it('loginWithDeviceFlowStart delegates to the forge adapter', async () => { const adapter = getAdapter('github'); @@ -76,7 +76,7 @@ describe('renderer/hooks/useLogins.ts', () => { expect(pollSpy).toHaveBeenCalledWith('session'); }); - it('loginWithDeviceFlowComplete calls addAccount', async () => { + it('loginWithDeviceFlowComplete creates the account', async () => { const { result } = renderLoginsHook(); await act(async () => { @@ -87,13 +87,7 @@ describe('renderer/hooks/useLogins.ts', () => { ); }); - expect(addAccountSpy).toHaveBeenCalledWith( - expect.anything(), - 'GitHub App', - 'token', - 'github.com', - 'github', - ); + expect(createAccountSpy).toHaveBeenCalledWith('GitHub App', 'token', 'github.com', 'github'); }); it('loginWithOAuthApp delegates to the forge adapter', async () => { @@ -163,6 +157,6 @@ describe('renderer/hooks/useLogins.ts', () => { }); expect(removeAccountNotificationsMock).toHaveBeenCalledWith(mockGitHubCloudAccount); - expect(removeAccountSpy).toHaveBeenCalledWith(expect.anything(), mockGitHubCloudAccount); + expect(removeAccountSpy).toHaveBeenCalledWith(mockGitHubCloudAccount); }); }); diff --git a/src/renderer/stores/useAccountsStore.test.ts b/src/renderer/stores/useAccountsStore.test.ts index b7812026e..96138c0c6 100644 --- a/src/renderer/stores/useAccountsStore.test.ts +++ b/src/renderer/stores/useAccountsStore.test.ts @@ -4,7 +4,16 @@ import { mockGitHubCloudAccount, mockGitHubEnterpriseServerAccount, } from '../__mocks__/account-mocks'; +import { mockRawUser } from '../utils/forges/github/__mocks__/response-mocks'; +import { Constants } from '../constants'; + +import type { Account, Hostname, Link, Token } from '../types'; +import type { GetAuthenticatedUserResponse } from '../utils/forges/github/types'; + +import { getRecommendedScopeNames } from '../utils/auth/scopes'; +import * as logger from '../utils/core/logger'; +import * as apiClient from '../utils/forges/github/client'; import { DEFAULT_ACCOUNTS_STATE } from './defaults'; import useAccountsStore from './useAccountsStore'; @@ -19,6 +28,139 @@ describe('renderer/stores/useAccountsStore.ts', () => { expect(result.current).toMatchObject(DEFAULT_ACCOUNTS_STATE); }); + describe('createAccount', () => { + vi.spyOn(logger, 'rendererLogInfo').mockImplementation(vi.fn()); + + const mockAuthenticatedResponse = mockRawUser('authenticated-user'); + + const fetchAuthenticatedUserDetailsSpy = vi.spyOn(apiClient, 'fetchAuthenticatedUserDetails'); + + const expectedUser = () => ({ + id: String(mockAuthenticatedResponse.id), + name: mockAuthenticatedResponse.name ?? null, + login: mockAuthenticatedResponse.login, + avatar: mockAuthenticatedResponse.avatar_url as Link, + }); + + describe('GitHub Cloud accounts', () => { + beforeEach(() => { + fetchAuthenticatedUserDetailsSpy.mockResolvedValue({ + status: 200, + url: 'https://api.github.com/user', + data: mockAuthenticatedResponse as GetAuthenticatedUserResponse, + headers: { + 'x-oauth-scopes': getRecommendedScopeNames().join(', '), + }, + }); + }); + + test('should add personal access token account', async () => { + await useAccountsStore + .getState() + .createAccount('Personal Access Token', '123-456' as Token, 'github.com' as Hostname); + + expect(useAccountsStore.getState().accounts).toEqual([ + { + forge: 'github', + hostname: 'github.com' as Hostname, + method: 'Personal Access Token', + platform: 'GitHub Cloud', + scopes: getRecommendedScopeNames(), + token: 'encrypted' as Token, + user: expectedUser(), + version: 'latest', + } satisfies Account, + ]); + }); + + test('should add oauth app account', async () => { + await useAccountsStore + .getState() + .createAccount('OAuth App', '123-456' as Token, 'github.com' as Hostname); + + expect(useAccountsStore.getState().accounts).toEqual([ + { + forge: 'github', + hostname: 'github.com' as Hostname, + method: 'OAuth App', + platform: 'GitHub Cloud', + scopes: getRecommendedScopeNames(), + token: 'encrypted' as Token, + user: expectedUser(), + version: 'latest', + } satisfies Account, + ]); + }); + + test('should replace an existing account on re-authentication', async () => { + await useAccountsStore + .getState() + .createAccount('Personal Access Token', '123-456' as Token, 'github.com' as Hostname); + await useAccountsStore + .getState() + .createAccount('Personal Access Token', '789-000' as Token, 'github.com' as Hostname); + + expect(useAccountsStore.getState().accounts).toHaveLength(1); + }); + }); + + describe('GitHub Enterprise Server accounts', () => { + beforeEach(() => { + fetchAuthenticatedUserDetailsSpy.mockResolvedValue({ + status: 200, + url: 'https://github.gitify.io/api/v3/user', + data: mockAuthenticatedResponse as GetAuthenticatedUserResponse, + headers: { + 'x-github-enterprise-version': '3.0.0', + 'x-oauth-scopes': getRecommendedScopeNames().join(', '), + }, + }); + }); + + test('should add personal access token account', async () => { + await useAccountsStore + .getState() + .createAccount( + 'Personal Access Token', + '123-456' as Token, + 'github.gitify.io' as Hostname, + ); + + expect(useAccountsStore.getState().accounts).toEqual([ + { + forge: 'github', + hostname: 'github.gitify.io' as Hostname, + method: 'Personal Access Token', + platform: 'GitHub Enterprise Server', + scopes: getRecommendedScopeNames(), + token: 'encrypted' as Token, + user: expectedUser(), + version: '3.0.0', + } satisfies Account, + ]); + }); + + test('should add oauth app account', async () => { + await useAccountsStore + .getState() + .createAccount('OAuth App', '123-456' as Token, 'github.gitify.io' as Hostname); + + expect(useAccountsStore.getState().accounts).toEqual([ + { + forge: 'github', + hostname: 'github.gitify.io' as Hostname, + method: 'OAuth App', + platform: 'GitHub Enterprise Server', + scopes: getRecommendedScopeNames(), + token: 'encrypted' as Token, + user: expectedUser(), + version: '3.0.0', + } satisfies Account, + ]); + }); + }); + }); + describe('removeAccount', () => { test('should remove an account', () => { useAccountsStore.setState({ @@ -89,6 +231,24 @@ describe('renderer/stores/useAccountsStore.ts', () => { }); }); + describe('primaryAccountHostname', () => { + test('should return first (primary) account hostname when multiple', () => { + useAccountsStore.setState({ + accounts: [mockGitHubCloudAccount, mockGitHubEnterpriseServerAccount], + }); + + const { result } = renderHook(() => useAccountsStore()); + + expect(result.current.primaryAccountHostname()).toBe(mockGitHubCloudAccount.hostname); + }); + + test('should use default hostname if no accounts', () => { + const { result } = renderHook(() => useAccountsStore()); + + expect(result.current.primaryAccountHostname()).toBe(Constants.GITHUB_HOSTNAME); + }); + }); + describe('reset', () => { test('should reset accounts to default', () => { useAccountsStore.setState({ diff --git a/src/renderer/stores/useAccountsStore.ts b/src/renderer/stores/useAccountsStore.ts index 07817df10..c6a682e24 100644 --- a/src/renderer/stores/useAccountsStore.ts +++ b/src/renderer/stores/useAccountsStore.ts @@ -7,17 +7,9 @@ import type { Account, Forge, Hostname, Token } from '../types'; import type { AuthMethod } from '../utils/auth/types'; import type { AccountsState, AccountsStore } from './types'; -import { - addAccount, - getAccountUUID, - getPrimaryAccountHostname, - hasAccounts, - hasMultipleAccounts, - isValidHostname, - refreshAccount, - removeAccount, -} from '../utils/auth/utils'; -import { rendererLogWarn } from '../utils/core/logger'; +import { resolvePlatform } from '../utils/auth/platform'; +import { getAccountUUID, isValidHostname, refreshAccount } from '../utils/auth/utils'; +import { rendererLogInfo, rendererLogWarn } from '../utils/core/logger'; import { getAdapter, isKnownForge } from '../utils/forges/registry'; import { decryptValue, encryptValue } from '../utils/system/comms'; import { DEFAULT_ACCOUNTS_STATE } from './defaults'; @@ -64,15 +56,43 @@ const useAccountsStore = create()( hostname: Hostname, forge: Forge = 'github', ) => { - const updated = await addAccount( - { accounts: [...get().accounts] }, - method, - token, - hostname, + const encryptedToken = (await encryptValue(token)) as Token; + + let newAccount: Account = { forge, + hostname: hostname, + method: method, + platform: resolvePlatform(forge, hostname), + token: encryptedToken, + user: null, // Will be updated during the refresh call below + }; + + newAccount = await refreshAccount(newAccount); + const newAccountUUID = getAccountUUID(newAccount); + + const accounts = get().accounts; + const existingAccount = accounts.find( + (account) => getAccountUUID(account) === newAccountUUID, ); - set({ accounts: updated.accounts }); + if (existingAccount) { + // Drop any forge-specific HTTP client cache so the new token is used. + getAdapter(existingAccount).onAccountTokenChange?.(existingAccount); + + // Replace the existing account (e.g. re-authentication with a new token) + rendererLogInfo( + 'createAccount', + `updating existing account for user ${newAccount.user?.login}`, + ); + + set({ + accounts: accounts.map((account) => + getAccountUUID(account) === newAccountUUID ? newAccount : account, + ), + }); + } else { + set({ accounts: [...accounts, newAccount] }); + } }, refreshAccount: async (account: Account): Promise => { @@ -90,12 +110,12 @@ const useAccountsStore = create()( }, removeAccount: (account) => { - const updated = removeAccount({ accounts: get().accounts }, account); - // Drop any forge-specific HTTP client state for the removed account. getAdapter(account).onAccountTokenChange?.(account); - set({ accounts: updated.accounts }); + set((state) => ({ + accounts: state.accounts.filter((a) => a.token !== account.token), + })); }, migrateAccountTokens: async () => { @@ -134,15 +154,15 @@ const useAccountsStore = create()( }, isLoggedIn: () => { - return hasAccounts({ accounts: get().accounts }); + return get().accounts.length > 0; }, hasMultipleAccounts: () => { - return hasMultipleAccounts({ accounts: get().accounts }); + return get().accounts.length > 1; }, primaryAccountHostname: () => { - return getPrimaryAccountHostname({ accounts: get().accounts }); + return get().accounts[0]?.hostname ?? Constants.GITHUB_HOSTNAME; }, reset: () => { diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 4d1bf1800..c2c2adfe9 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -133,10 +133,6 @@ export interface SystemSettingsState { keepWindowOnBlur: boolean; } -export interface AuthState { - accounts: Account[]; -} - export enum Theme { SYSTEM = 'SYSTEM', LIGHT = 'LIGHT', diff --git a/src/renderer/utils/auth/utils.test.ts b/src/renderer/utils/auth/utils.test.ts index 9a3079c5d..76e774291 100644 --- a/src/renderer/utils/auth/utils.test.ts +++ b/src/renderer/utils/auth/utils.test.ts @@ -1,191 +1,10 @@ import { mockGitHubCloudAccount } from '../../__mocks__/account-mocks'; -import { mockAuth } from '../../__mocks__/state-mocks'; -import { mockRawUser } from '../forges/github/__mocks__/response-mocks'; -import { Constants } from '../../constants'; +import type { Hostname } from '../../types'; -import type { Account, AuthState, Hostname, Link, Token } from '../../types'; -import type { GetAuthenticatedUserResponse } from '../forges/github/types'; - -import * as logger from '../core/logger'; -import * as apiClient from '../forges/github/client'; -import { getRecommendedScopeNames } from './scopes'; import * as authUtils from './utils'; describe('renderer/utils/auth/utils.ts', () => { - vi.spyOn(logger, 'rendererLogInfo').mockImplementation(vi.fn()); - - describe('addAccount', () => { - let mockAuthState: AuthState; - - const mockAuthenticatedResponse = mockRawUser('authenticated-user'); - - const fetchAuthenticatedUserDetailsSpy = vi.spyOn(apiClient, 'fetchAuthenticatedUserDetails'); - - beforeEach(() => { - mockAuthState = { - accounts: [], - }; - }); - - describe('should add GitHub Cloud account', () => { - beforeEach(() => { - fetchAuthenticatedUserDetailsSpy.mockResolvedValue({ - status: 200, - url: 'https://api.github.com/user', - data: mockAuthenticatedResponse as GetAuthenticatedUserResponse, - headers: { - 'x-oauth-scopes': getRecommendedScopeNames().join(', '), - }, - }); - }); - - it('should add personal access token account', async () => { - const result = await authUtils.addAccount( - mockAuthState, - 'Personal Access Token', - '123-456' as Token, - 'github.com' as Hostname, - ); - - expect(result.accounts).toEqual([ - { - forge: 'github', - hostname: 'github.com' as Hostname, - method: 'Personal Access Token', - platform: 'GitHub Cloud', - scopes: getRecommendedScopeNames(), - token: 'encrypted' as Token, - user: { - id: String(mockAuthenticatedResponse.id), - name: mockAuthenticatedResponse.name ?? null, - login: mockAuthenticatedResponse.login, - avatar: mockAuthenticatedResponse.avatar_url as Link, - }, - version: 'latest', - } satisfies Account, - ]); - }); - - it('should add oauth app account', async () => { - const result = await authUtils.addAccount( - mockAuthState, - 'OAuth App', - '123-456' as Token, - 'github.com' as Hostname, - ); - - expect(result.accounts).toEqual([ - { - forge: 'github', - hostname: 'github.com' as Hostname, - method: 'OAuth App', - platform: 'GitHub Cloud', - scopes: getRecommendedScopeNames(), - token: 'encrypted' as Token, - user: { - id: String(mockAuthenticatedResponse.id), - name: mockAuthenticatedResponse.name ?? null, - login: mockAuthenticatedResponse.login, - avatar: mockAuthenticatedResponse.avatar_url as Link, - }, - version: 'latest', - } satisfies Account, - ]); - }); - }); - - describe('should add GitHub Enterprise Server account', () => { - beforeEach(() => { - fetchAuthenticatedUserDetailsSpy.mockResolvedValue({ - status: 200, - url: 'https://github.gitify.io/api/v3/user', - data: mockAuthenticatedResponse as GetAuthenticatedUserResponse, - headers: { - 'x-github-enterprise-version': '3.0.0', - 'x-oauth-scopes': getRecommendedScopeNames().join(', '), - }, - }); - }); - - it('should add personal access token account', async () => { - const result = await authUtils.addAccount( - mockAuthState, - 'Personal Access Token', - '123-456' as Token, - 'github.gitify.io' as Hostname, - ); - - expect(result.accounts).toEqual([ - { - forge: 'github', - hostname: 'github.gitify.io' as Hostname, - method: 'Personal Access Token', - platform: 'GitHub Enterprise Server', - scopes: getRecommendedScopeNames(), - token: 'encrypted' as Token, - user: { - id: String(mockAuthenticatedResponse.id), - name: mockAuthenticatedResponse.name ?? null, - login: mockAuthenticatedResponse.login, - avatar: mockAuthenticatedResponse.avatar_url as Link, - }, - version: '3.0.0', - } satisfies Account, - ]); - }); - - it('should add oauth app account', async () => { - const result = await authUtils.addAccount( - mockAuthState, - 'OAuth App', - '123-456' as Token, - 'github.gitify.io' as Hostname, - ); - - expect(result.accounts).toEqual([ - { - forge: 'github', - hostname: 'github.gitify.io' as Hostname, - method: 'OAuth App', - platform: 'GitHub Enterprise Server', - scopes: getRecommendedScopeNames(), - token: 'encrypted' as Token, - user: { - id: String(mockAuthenticatedResponse.id), - name: mockAuthenticatedResponse.name ?? null, - login: mockAuthenticatedResponse.login, - avatar: mockAuthenticatedResponse.avatar_url as Link, - }, - version: '3.0.0', - } satisfies Account, - ]); - }); - }); - }); - - describe('removeAccount', () => { - it('should remove account with matching token', async () => { - expect(mockAuth.accounts.length).toBe(2); - - const result = authUtils.removeAccount(mockAuth, mockGitHubCloudAccount); - - expect(result.accounts.length).toBe(1); - }); - - it('should do nothing if no accounts match', async () => { - const mockAccount = { - token: 'unknown-token', - } as Account; - - expect(mockAuth.accounts.length).toBe(2); - - const result = authUtils.removeAccount(mockAuth, mockAccount); - - expect(result.accounts.length).toBe(2); - }); - }); - describe('isValidHostname', () => { it('should validate hostname - github cloud', () => { expect(authUtils.isValidHostname('github.com' as Hostname)).toBeTruthy(); @@ -211,47 +30,4 @@ describe('renderer/utils/auth/utils.ts', () => { ); }); }); - - describe('getPrimaryAccountHostname', () => { - it('should return first (primary) account hostname when multiple', () => { - expect(authUtils.getPrimaryAccountHostname(mockAuth)).toBe(mockGitHubCloudAccount.hostname); - }); - - it('should use default hostname if no accounts', () => { - expect(authUtils.getPrimaryAccountHostname({ accounts: [] })).toBe(Constants.GITHUB_HOSTNAME); - }); - }); - - describe('hasAccounts', () => { - it('should return true', () => { - expect(authUtils.hasAccounts(mockAuth)).toBeTruthy(); - }); - - it('should validate false', () => { - expect( - authUtils.hasAccounts({ - accounts: [], - }), - ).toBeFalsy(); - }); - }); - - describe('hasMultipleAccounts', () => { - it('should return true', () => { - expect(authUtils.hasMultipleAccounts(mockAuth)).toBeTruthy(); - }); - - it('should validate false', () => { - expect( - authUtils.hasMultipleAccounts({ - accounts: [], - }), - ).toBeFalsy(); - expect( - authUtils.hasMultipleAccounts({ - accounts: [mockGitHubCloudAccount], - }), - ).toBeFalsy(); - }); - }); }); diff --git a/src/renderer/utils/auth/utils.ts b/src/renderer/utils/auth/utils.ts index 2cc56955d..283b16c81 100644 --- a/src/renderer/utils/auth/utils.ts +++ b/src/renderer/utils/auth/utils.ts @@ -1,81 +1,9 @@ -import { Constants } from '../../constants'; +import type { Account, AccountUUID, Hostname, Link } from '../../types'; -import type { Account, AccountUUID, AuthState, Forge, Hostname, Link, Token } from '../../types'; -import type { AuthMethod } from './types'; - -import { rendererLogError, rendererLogInfo, rendererLogWarn, toError } from '../core/logger'; +import { rendererLogError, rendererLogWarn, toError } from '../core/logger'; import { getAdapter } from '../forges/registry'; -import { encryptValue } from '../system/comms'; -import { resolvePlatform } from './platform'; import { hasRequiredScopes } from './scopes'; -/** - * Add or update an account in the auth state. - * - * Encrypts the token, refreshes the user profile, then upserts the account: - * if an account with the same UUID (hostname + user ID + method) already - * exists it is replaced (e.g. on re-authentication); otherwise it is appended. - * - * @param auth - The current auth state. - * @param method - The authentication method used. - * @param token - The plaintext access token to store (will be encrypted). - * @param hostname - The forge hostname for the account. - * @returns The updated auth state. - */ -export async function addAccount( - auth: AuthState, - method: AuthMethod, - token: Token, - hostname: Hostname, - forge: Forge = 'github', -): Promise { - const accountList = auth.accounts; - const encryptedToken = await encryptValue(token); - - let newAccount = { - forge, - hostname: hostname, - method: method, - platform: resolvePlatform(forge, hostname), - token: encryptedToken, - user: null, // Will be updated during the refresh call below - } as Account; - - newAccount = await refreshAccount(newAccount); - const newAccountUUID = getAccountUUID(newAccount); - - const existingIndex = accountList.findIndex((a) => getAccountUUID(a) === newAccountUUID); - - if (existingIndex >= 0) { - // Drop any forge-specific HTTP client cache so the new token is used. - getAdapter(accountList[existingIndex]).onAccountTokenChange?.(accountList[existingIndex]); - // Replace the existing account (e.g. re-authentication with a new token) - rendererLogInfo('addAccount', `updating existing account for user ${newAccount.user?.login}`); - accountList[existingIndex] = newAccount; - } else { - accountList.push(newAccount); - } - - return { - accounts: accountList, - }; -} - -/** - * Remove an account from the auth state. - * - * @param auth - The current auth state. - * @param account - The account to remove. - * @returns A new auth state with the account removed. - */ -export function removeAccount(auth: AuthState, account: Account): AuthState { - const updatedAccounts = auth.accounts.filter((a) => a.token !== account.token); - - return { - accounts: updatedAccounts, - }; -} - /** * Refresh an account's user profile, version, and OAuth scopes from the API. * @@ -140,32 +68,3 @@ export function isValidHostname(hostname: Hostname) { export function getAccountUUID(account: Account): AccountUUID { return btoa(`${account.hostname}-${account.user?.id}-${account.method}`) as AccountUUID; } - -/** - * Return the primary (first) account hostname, or the default GitHub.com hostname - * if no accounts are present. - * - * @param auth - The current auth state. - * @returns The hostname of the first account. - */ -export function getPrimaryAccountHostname(auth: AuthState) { - return auth.accounts[0]?.hostname ?? Constants.GITHUB_HOSTNAME; -} - -/** - * Return true if at least one account is authenticated. - * - * @param auth - The current auth state. - */ -export function hasAccounts(auth: AuthState) { - return auth.accounts.length > 0; -} - -/** - * Return true if more than one account is authenticated. - * - * @param auth - The current auth state. - */ -export function hasMultipleAccounts(auth: AuthState) { - return auth.accounts.length > 1; -} diff --git a/src/renderer/utils/notifications/notifications.ts b/src/renderer/utils/notifications/notifications.ts index 5904cb543..e396de06a 100644 --- a/src/renderer/utils/notifications/notifications.ts +++ b/src/renderer/utils/notifications/notifications.ts @@ -1,8 +1,8 @@ import { useAccountsStore, useSettingsStore } from '../../stores'; import type { + Account, AccountNotifications, - AuthState, RawGitifyNotification, SettingsState, } from '../../types'; @@ -37,8 +37,8 @@ export function getUnreadNotificationCount(accountNotifications: AccountNotifica ); } -function getNotifications(auth: AuthState, settings: SettingsState) { - return auth.accounts.map((account) => { +function getNotifications(accounts: Account[], settings: SettingsState) { + return accounts.map((account) => { return { account, notifications: getAdapter(account).listNotifications(account, settings), @@ -61,11 +61,10 @@ function getNotifications(auth: AuthState, settings: SettingsState) { * @returns A promise that resolves to an array of account notifications. */ export async function getAllNotifications(): Promise { - const auth: AuthState = { accounts: useAccountsStore.getState().accounts }; const settings = useSettingsStore.getState(); const accountNotifications: AccountNotifications[] = await Promise.all( - getNotifications(auth, settings) + getNotifications(useAccountsStore.getState().accounts, settings) .filter((response) => !!response) .map(async (accountNotifications) => { try {