From 1ed0081464e84889a5c80b2bb7bee6c0d423138b Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Mon, 29 Apr 2024 10:42:09 -1000 Subject: [PATCH 01/13] feat: add accounts route and view --- src/app.tsx | 9 ++ src/components/Sidebar.tsx | 15 +++ src/context/App.tsx | 25 ++++- src/routes/Accounts.tsx | 164 +++++++++++++++++++++++++++++++++ src/routes/LoginEnterprise.tsx | 12 +-- src/utils/auth.ts | 14 +++ 6 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 src/routes/Accounts.tsx diff --git a/src/app.tsx b/src/app.tsx index 9ae971b14..7e240cf49 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -10,6 +10,7 @@ import { import { Loading } from './components/Loading'; import { Sidebar } from './components/Sidebar'; import { AppContext, AppProvider } from './context/App'; +import { AccountsRoute } from './routes/Accounts'; import { LoginRoute } from './routes/Login'; import { LoginEnterpriseRoute } from './routes/LoginEnterprise'; import { LoginWithToken } from './routes/LoginWithToken'; @@ -51,6 +52,14 @@ export const App = () => { } /> + + + + } + /> } /> { className={status === 'loading' ? 'animate-spin' : undefined} /> + + +

Accounts

+ + +
+
+
GitHub.com
+ {!accounts?.token && ( +
+ +
+ )} +
+ +
+
+ {accounts?.token && ( + <> +
openProfile(accounts.user.login)} + onKeyDown={() => openProfile(accounts.user.login)} + > + @{accounts.user.login}{' '} + ({accounts.user.name}) +
+
+ +
+ + )} +
+
+ +
+
+
+ GitHub Enterprise Server +
+
+ +
+
+ + {accounts.enterpriseAccounts.map((enterpriseAccount) => ( +
+
+
+
+ openEnterpriseServer(enterpriseAccount.hostname) + } + onKeyDown={() => + openEnterpriseServer(enterpriseAccount.hostname) + } + > + {enterpriseAccount.hostname} +
+
+ +
+ +
+
+
+ ))} +
+
+ + ); +}; diff --git a/src/routes/LoginEnterprise.tsx b/src/routes/LoginEnterprise.tsx index c025ba327..14e8a57e0 100644 --- a/src/routes/LoginEnterprise.tsx +++ b/src/routes/LoginEnterprise.tsx @@ -58,12 +58,12 @@ export const LoginEnterpriseRoute: FC = () => { } = useContext(AppContext); const navigate = useNavigate(); - useEffect(() => { - if (enterpriseAccounts.length) { - ipcRenderer.send('reopen-window'); - navigate(-1); - } - }, [enterpriseAccounts]); + // useEffect(() => { + // if (enterpriseAccounts.length) { + // ipcRenderer.send('reopen-window'); + // navigate(-1); + // } + // }, [enterpriseAccounts]); const renderForm = (formProps: FormRenderProps) => { const { handleSubmit, submitting, pristine } = formProps; diff --git a/src/utils/auth.ts b/src/utils/auth.ts index 222e1900d..d8e9155ad 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -136,3 +136,17 @@ export const addAccount = ( ], }; }; + +export const removeAccount = ( + accounts: AuthState, + hostname: string, +): AuthState => { + if (!isEnterpriseHost(hostname)) { + return { + ...accounts, + enterpriseAccounts: accounts.enterpriseAccounts.filter( + (account) => account.hostname !== hostname, + ), + }; + } +}; From e96c8129f9a6dbb3fadfec5f3da898fc37cb9e4f Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Mon, 3 Jun 2024 08:40:11 -0400 Subject: [PATCH 02/13] feat: accounts view --- src/routes/Accounts.test.tsx | 75 ++++++++++++ src/routes/Settings.test.tsx | 107 +----------------- .../__snapshots__/Settings.test.tsx.snap | 75 +----------- 3 files changed, 79 insertions(+), 178 deletions(-) create mode 100644 src/routes/Accounts.test.tsx diff --git a/src/routes/Accounts.test.tsx b/src/routes/Accounts.test.tsx new file mode 100644 index 000000000..cbdcf1033 --- /dev/null +++ b/src/routes/Accounts.test.tsx @@ -0,0 +1,75 @@ +import { act, fireEvent, render, screen } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import { + mockOAuthAccount, + mockPersonalAccessTokenAccount, + mockSettings, +} from '../__mocks__/state-mocks'; +import { AppContext } from '../context/App'; +import { AccountsRoute } from './Accounts'; + +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); + +describe('routes/Accounts.tsx', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('login with personal access token', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + expect(screen.getByTitle('Login with Personal Access Token').hidden).toBe( + false, + ); + + fireEvent.click(screen.getByTitle('Login with Personal Access Token')); + expect(mockNavigate).toHaveBeenNthCalledWith( + 1, + '/login-personal-access-token', + { + replace: true, + }, + ); + }); + + it('login with oauth app', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + expect(screen.getByTitle('Login with OAuth App').hidden).toBe(false); + + fireEvent.click(screen.getByTitle('Login with OAuth App')); + expect(mockNavigate).toHaveBeenNthCalledWith(1, '/login-oauth-app', { + replace: true, + }); + }); +}); diff --git a/src/routes/Settings.test.tsx b/src/routes/Settings.test.tsx index 2edc874b2..fe1223055 100644 --- a/src/routes/Settings.test.tsx +++ b/src/routes/Settings.test.tsx @@ -1,12 +1,7 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; import { ipcRenderer, shell } from 'electron'; import { MemoryRouter } from 'react-router-dom'; -import { - mockAuth, - mockOAuthAccount, - mockPersonalAccessTokenAccount, - mockSettings, -} from '../__mocks__/state-mocks'; +import { mockAuth, mockSettings } from '../__mocks__/state-mocks'; import { mockPlatform } from '../__mocks__/utils'; import { AppContext } from '../context/App'; import { SettingsRoute } from './Settings'; @@ -483,104 +478,6 @@ describe('routes/Settings.tsx', () => { ); }); - describe('Login with Personal Access Token', () => { - it('should show login with personal access token button if not logged in', async () => { - await act(async () => { - render( - - - - - , - ); - }); - - expect( - screen.getByTitle('Login with Personal Access Token').hidden, - ).toBe(false); - - fireEvent.click(screen.getByTitle('Login with Personal Access Token')); - expect(mockNavigate).toHaveBeenNthCalledWith( - 1, - '/login-personal-access-token', - { - replace: true, - }, - ); - }); - - it('should hide login with personal access token button if already logged in', async () => { - await act(async () => { - render( - - - - - , - ); - }); - - expect( - screen.getByTitle('Login with Personal Access Token').hidden, - ).toBe(true); - }); - }); - - describe('Login with OAuth App', () => { - it('should show login with oauth app if not logged in', async () => { - await act(async () => { - render( - - - - - , - ); - }); - - expect(screen.getByTitle('Login with OAuth App').hidden).toBe(false); - - fireEvent.click(screen.getByTitle('Login with OAuth App')); - expect(mockNavigate).toHaveBeenNthCalledWith(1, '/login-oauth-app', { - replace: true, - }); - }); - - it('should hide login with oauth app route if already logged in', async () => { - await act(async () => { - render( - - - - - , - ); - }); - - expect(screen.getByTitle('Login with OAuth App').hidden).toBe(true); - }); - }); - it('should press the logout', async () => { const logoutMock = jest.fn(); await act(async () => { @@ -599,7 +496,7 @@ describe('routes/Settings.tsx', () => { ); }); - fireEvent.click(screen.getByTitle('Logout')); + fireEvent.click(screen.getByTitle('Logout Gitify')); expect(logoutMock).toHaveBeenCalledTimes(1); diff --git a/src/routes/__snapshots__/Settings.test.tsx.snap b/src/routes/__snapshots__/Settings.test.tsx.snap index e95556fe0..9a66ad127 100644 --- a/src/routes/__snapshots__/Settings.test.tsx.snap +++ b/src/routes/__snapshots__/Settings.test.tsx.snap @@ -511,85 +511,14 @@ exports[`routes/Settings.tsx General should render itself & its children 1`] = ` 0.0.1
- -
- + ))} @@ -120,6 +176,7 @@ export const AccountsRoute: FC = () => { className={buttonClass} title="Login with Personal Access Token" onClick={loginWithPersonalAccessToken} + hidden={isPersonalAccessTokenLoggedIn(auth)} > @@ -129,6 +186,7 @@ export const AccountsRoute: FC = () => { className={buttonClass} title="Login with OAuth App" onClick={loginWithOAuthApp} + hidden={isOAuthAppLoggedIn(auth)} > diff --git a/src/utils/auth/utils.test.ts b/src/utils/auth/utils.test.ts index 98ffa610f..2f42234a8 100644 --- a/src/utils/auth/utils.test.ts +++ b/src/utils/auth/utils.test.ts @@ -215,6 +215,27 @@ describe('utils/auth/utils.ts', () => { }); }); + it('getDeveloperSettingsURL', () => { + expect( + auth.getDeveloperSettingsURL({ + hostname: 'github.com', + method: 'GitHub App', + } as Account), + ).toBe('https://github.com/settings/apps'); + expect( + auth.getDeveloperSettingsURL({ + hostname: 'github.com', + method: 'OAuth App', + } as Account), + ).toBe('https://github.com/settings/developers'); + expect( + auth.getDeveloperSettingsURL({ + hostname: 'github.com', + method: 'Personal Access Token', + } as Account), + ).toBe('https://github.com/settings/tokens'); + }); + describe('getNewTokenURL', () => { it('should generate new PAT url - github cloud', () => { expect( diff --git a/src/utils/auth/utils.ts b/src/utils/auth/utils.ts index 89b954d80..f4ab7fe4a 100644 --- a/src/utils/auth/utils.ts +++ b/src/utils/auth/utils.ts @@ -138,6 +138,23 @@ export function removeAccount(auth: AuthState, account: Account): AuthState { }; } +export function getDeveloperSettingsURL(account: Account): string { + const settingsURL = new URL(`https://${account.hostname}`); + + switch (account.method) { + case 'GitHub App': + settingsURL.pathname = '/settings/apps'; + break; + case 'OAuth App': + settingsURL.pathname = '/settings/developers'; + break; + case 'Personal Access Token': + settingsURL.pathname = 'settings/tokens'; + break; + } + return settingsURL.toString(); +} + export function getNewTokenURL(hostname: string): string { const date = format(new Date(), 'PP p'); const newTokenURL = new URL(`https://${hostname}/settings/tokens/new`); @@ -181,3 +198,7 @@ export function isValidClientId(clientId: string) { export function isValidToken(token: string) { return /^[A-Z0-9_]{40}$/i.test(token); } + +export function getAccountUUID(account: Account): string { + return btoa(`${account.hostname}-${account.user.id}-${account.method}`); +} From eaa3b98822f2738e4c6ae60e53bf7ab43d2c0297 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Mon, 3 Jun 2024 15:22:35 -0400 Subject: [PATCH 05/13] feat: accounts view --- src/routes/Settings.test.tsx | 2 +- src/routes/Settings.tsx | 4 ++-- src/routes/__snapshots__/Settings.test.tsx.snap | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/routes/Settings.test.tsx b/src/routes/Settings.test.tsx index fe1223055..416697771 100644 --- a/src/routes/Settings.test.tsx +++ b/src/routes/Settings.test.tsx @@ -496,7 +496,7 @@ describe('routes/Settings.tsx', () => { ); }); - fireEvent.click(screen.getByTitle('Logout Gitify')); + fireEvent.click(screen.getByTitle('Logout of Gitify')); expect(logoutMock).toHaveBeenCalledTimes(1); diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx index 318155108..fdb128a49 100644 --- a/src/routes/Settings.tsx +++ b/src/routes/Settings.tsx @@ -279,11 +279,11 @@ export const SettingsRoute: FC = () => { +

+ Accounts +

+ +
+
+
+
+
+ @ + octocat + + - + Mona Lisa Octocat + +
+
+ + + + GitHub Cloud + - + github.com +
+
+ + + + Personal Access Token +
+
+
+ +
+
+
+
+
+ @ + octocat + + - + Mona Lisa Octocat + +
+
+ + + + GitHub Enterprise Server + - + github.gitify.io +
+
+ + + + Personal Access Token +
+
+
+ +
+
+
+
+
+
+ Add new account +
+
+ + +
+
+ +`; From 977cbbc19f894c7031e0a72bfdc1104eac0221db Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Mon, 3 Jun 2024 16:12:37 -0400 Subject: [PATCH 09/13] add unit tests --- src/__mocks__/state-mocks.ts | 8 + src/routes/Accounts.test.tsx | 183 +++++++++++++++--- src/routes/Accounts.tsx | 27 ++- .../__snapshots__/Accounts.test.tsx.snap | 132 +++++++++++-- 4 files changed, 292 insertions(+), 58 deletions(-) diff --git a/src/__mocks__/state-mocks.ts b/src/__mocks__/state-mocks.ts index 118e11bbe..da9091ec5 100644 --- a/src/__mocks__/state-mocks.ts +++ b/src/__mocks__/state-mocks.ts @@ -53,6 +53,14 @@ export const mockGitHubEnterpriseServerAccount: Account = { user: mockGitifyUser, }; +export const mockGitHubAppAccount: Account = { + platform: 'GitHub Cloud', + method: 'GitHub App', + token: '987654321', + hostname: Constants.DEFAULT_AUTH_OPTIONS.hostname, + user: mockGitifyUser, +}; + export const mockAuth: AuthState = { accounts: [mockGitHubCloudAccount, mockGitHubEnterpriseServerAccount], }; diff --git a/src/routes/Accounts.test.tsx b/src/routes/Accounts.test.tsx index 191f1fbee..1693605ad 100644 --- a/src/routes/Accounts.test.tsx +++ b/src/routes/Accounts.test.tsx @@ -1,7 +1,9 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; +import { ipcRenderer, shell } from 'electron'; import { MemoryRouter } from 'react-router-dom'; import { mockAuth, + mockGitHubAppAccount, mockOAuthAccount, mockPersonalAccessTokenAccount, mockSettings, @@ -25,7 +27,16 @@ describe('routes/Accounts.tsx', () => { await act(async () => { render( @@ -58,13 +69,15 @@ describe('routes/Accounts.tsx', () => { }); }); - describe('Login with Personal Access Token', () => { - it('should show login with personal access token button if not logged in', async () => { + describe('Account interactions', () => { + it('open profile in external browser', async () => { await act(async () => { render( @@ -75,26 +88,22 @@ describe('routes/Accounts.tsx', () => { ); }); - expect(screen.getByTitle('Login with Personal Access Token').hidden).toBe( - false, - ); + fireEvent.click(screen.getByTitle('Open Profile')); - fireEvent.click(screen.getByTitle('Login with Personal Access Token')); - expect(mockNavigate).toHaveBeenNthCalledWith( - 1, - '/login-personal-access-token', - { - replace: true, - }, + expect(shell.openExternal).toHaveBeenCalledTimes(1); + expect(shell.openExternal).toHaveBeenCalledWith( + 'https://github.com/octocat', ); }); - it('should hide login with personal access token button if already logged in', async () => { + it('open host in external browser', async () => { await act(async () => { render( @@ -105,19 +114,20 @@ describe('routes/Accounts.tsx', () => { ); }); - expect(screen.getByTitle('Login with Personal Access Token').hidden).toBe( - true, - ); + fireEvent.click(screen.getByTitle('Open Host')); + + expect(shell.openExternal).toHaveBeenCalledTimes(1); + expect(shell.openExternal).toHaveBeenCalledWith('https://github.com'); }); - }); - describe('Login with OAuth App', () => { - it('should show login with oauth app if not logged in', async () => { + it('open developer settings in external browser', async () => { await act(async () => { render( @@ -128,21 +138,25 @@ describe('routes/Accounts.tsx', () => { ); }); - expect(screen.getByTitle('Login with OAuth App').hidden).toBe(false); + fireEvent.click(screen.getByTitle('Open Developer Settings')); - fireEvent.click(screen.getByTitle('Login with OAuth App')); - expect(mockNavigate).toHaveBeenNthCalledWith(1, '/login-oauth-app', { - replace: true, - }); + expect(shell.openExternal).toHaveBeenCalledTimes(1); + expect(shell.openExternal).toHaveBeenCalledWith( + 'https://github.com/settings/tokens', + ); }); - it('should hide login with oauth app route if already logged in', async () => { + it('should logout', async () => { + const logoutFromAccountMock = jest.fn(); await act(async () => { render( @@ -152,7 +166,114 @@ describe('routes/Accounts.tsx', () => { ); }); - expect(screen.getByTitle('Login with OAuth App').hidden).toBe(true); + fireEvent.click(screen.getByTitle('Logout octocat')); + + expect(logoutFromAccountMock).toHaveBeenCalledTimes(1); + + expect(ipcRenderer.send).toHaveBeenCalledTimes(2); + expect(ipcRenderer.send).toHaveBeenCalledWith('update-icon'); + expect(ipcRenderer.send).toHaveBeenCalledWith('update-title', ''); + expect(mockNavigate).toHaveBeenNthCalledWith(1, -1); + }); + }); + + describe('Add new accounts', () => { + describe('Login with Personal Access Token', () => { + it('should show login with personal access token button if not logged in', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + expect( + screen.getByTitle('Login with Personal Access Token').hidden, + ).toBe(false); + + fireEvent.click(screen.getByTitle('Login with Personal Access Token')); + expect(mockNavigate).toHaveBeenNthCalledWith( + 1, + '/login-personal-access-token', + { + replace: true, + }, + ); + }); + + it('should hide login with personal access token button if already logged in', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + expect( + screen.getByTitle('Login with Personal Access Token').hidden, + ).toBe(true); + }); + }); + + describe('Login with OAuth App', () => { + it('should show login with oauth app if not logged in', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + expect(screen.getByTitle('Login with OAuth App').hidden).toBe(false); + + fireEvent.click(screen.getByTitle('Login with OAuth App')); + expect(mockNavigate).toHaveBeenNthCalledWith(1, '/login-oauth-app', { + replace: true, + }); + }); + + it('should hide login with oauth app route if already logged in', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + expect(screen.getByTitle('Login with OAuth App').hidden).toBe(true); + }); }); }); }); diff --git a/src/routes/Accounts.tsx b/src/routes/Accounts.tsx index df8c4f6c0..09c32d56b 100644 --- a/src/routes/Accounts.tsx +++ b/src/routes/Accounts.tsx @@ -37,6 +37,12 @@ export const AccountsRoute: FC = () => { updateTrayTitle(); }, []); + const openProfile = (account: Account) => { + const url = new URL(`https://${account.hostname}`); + url.pathname = account.user.login; + openExternalLink(url.toString()); + }; + const openHost = (hostname: string) => { openExternalLink(`https://${hostname}`); }; @@ -87,9 +93,11 @@ export const AccountsRoute: FC = () => { className="flex justify-between items-center bg-gray-100 dark:bg-gray-900 rounded-md p-1 mb-4" >
-
openProfile(account)} > @{account.user.login} { > - {account.user?.name} -
+ -
openHost(account.hostname)} - onKeyDown={() => openHost(account.hostname)} > {account.platform === 'GitHub Cloud' ? ( { /> ) : null} {account.platform} - {account.hostname} -
-
+
+
+
+ OAuth App + + +
+ +
+ +
+
+ + +
-
+ + - - - From 4ca7bda622652097bfc00cef903388a885e2d17f Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 4 Jun 2024 11:42:09 -0400 Subject: [PATCH 12/13] remove master logout --- src/routes/Settings.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx index d545b2119..aa9c933da 100644 --- a/src/routes/Settings.tsx +++ b/src/routes/Settings.tsx @@ -266,11 +266,7 @@ export const SettingsRoute: FC = () => { className={footerButtonClass} title="Accounts" onClick={() => { - if (location.pathname.startsWith('/accounts')) { - navigate('/', { replace: true }); - } else { - navigate('/accounts'); - } + navigate('/accounts'); }} > From ea1e52fc7b6faf9ad4047b2bf0a87e763229c080 Mon Sep 17 00:00:00 2001 From: Afonso Jorge Ramos Date: Thu, 6 Jun 2024 01:41:57 +0100 Subject: [PATCH 13/13] chore: merge `main` --- .vscode/launch.json | 40 +- biome.json | 2 +- package.json | 12 +- pnpm-lock.yaml | 230 +- src/__mocks__/state-mocks.ts | 1 + src/components/NotificationRow.test.tsx | 144 +- src/components/NotificationRow.tsx | 219 +- .../NotificationRow.test.tsx.snap | 1987 +++++++++-------- src/components/fields/Tooltip.tsx | 2 +- .../__snapshots__/Tooltip.test.tsx.snap | 2 +- src/context/App.test.tsx | 20 +- src/context/App.tsx | 1 + src/routes/Settings.test.tsx | 25 + src/routes/Settings.tsx | 76 +- .../__snapshots__/Settings.test.tsx.snap | 48 + src/types.ts | 1 + src/utils/constants.ts | 2 +- 17 files changed, 1616 insertions(+), 1196 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d6c287fe8..0600cdc0d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,21 +1,21 @@ { - // Use IntelliSense to learn about possible Node.js debug attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Launch Program", - "program": "${workspaceRoot}/main.js" - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Process", - "address": "localhost", - "port": 5858 - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceRoot}/main.js" + }, + { + "type": "node", + "request": "attach", + "name": "Attach to Process", + "address": "localhost", + "port": 5858 + } + ] +} diff --git a/biome.json b/biome.json index 8431db89a..b14e36ec4 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json", + "$schema": "https://biomejs.dev/schemas/1.8.0/schema.json", "organizeImports": { "enabled": true }, diff --git a/package.json b/package.json index 47ce3088f..a8b56ec96 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "make:linux": "electron-builder --linux", "make:macos": "electron-builder --mac --universal", "make:win": "electron-builder --win", - "lint:check": "biome check *", - "lint": "biome check --apply *", + "lint:check": "biome check", + "lint": "biome check --fix", "test": "jest", "start": "electron . --enable-logging", "prepare": "husky" @@ -111,7 +111,7 @@ "@primer/octicons-react": "19.9.0", "axios": "1.7.2", "date-fns": "3.6.0", - "electron-updater": "6.1.8", + "electron-updater": "6.2.1", "final-form": "4.20.10", "menubar": "9.4.0", "nprogress": "0.2.0", @@ -124,11 +124,11 @@ "typescript": "5.4.5" }, "devDependencies": { - "@biomejs/biome": "1.7.3", + "@biomejs/biome": "1.8.0", "@electron/notarize": "2.3.2", - "@testing-library/react": "15.0.7", + "@testing-library/react": "16.0.0", "@types/jest": "29.5.12", - "@types/node": "20.14.0", + "@types/node": "20.14.2", "@types/nprogress": "0.2.3", "@types/react": "18.3.3", "@types/react-router-dom": "5.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9923dff6b..06969699c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: 3.6.0 version: 3.6.0 electron-updater: - specifier: 6.1.8 - version: 6.1.8 + specifier: 6.2.1 + version: 6.2.1 final-form: specifier: 4.20.10 version: 4.20.10 @@ -55,20 +55,20 @@ importers: version: 5.4.5 devDependencies: '@biomejs/biome': - specifier: 1.7.3 - version: 1.7.3 + specifier: 1.8.0 + version: 1.8.0 '@electron/notarize': specifier: 2.3.2 version: 2.3.2 '@testing-library/react': - specifier: 15.0.7 - version: 15.0.7(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 16.0.0 + version: 16.0.0(@testing-library/dom@10.0.0)(@types/react-dom@18.2.22)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/node': - specifier: 20.14.0 - version: 20.14.0 + specifier: 20.14.2 + version: 20.14.2 '@types/nprogress': specifier: 0.2.3 version: 0.2.3 @@ -101,7 +101,7 @@ importers: version: 9.0.11 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) jest-environment-jsdom: specifier: 29.7.0 version: 29.7.0 @@ -122,13 +122,13 @@ importers: version: 4.0.0(webpack@5.91.0(webpack-cli@5.1.4)) tailwindcss: specifier: 3.4.3 - version: 3.4.3(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + version: 3.4.3(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) ts-jest: specifier: 29.1.4 - version: 29.1.4(@babel/core@7.24.3)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.3))(jest@29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.1.4(@babel/core@7.24.3)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.3))(jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)))(typescript@5.4.5) ts-node: specifier: 10.9.2 - version: 10.9.2(@types/node@20.14.0)(typescript@5.4.5) + version: 10.9.2(@types/node@20.14.2)(typescript@5.4.5) webpack: specifier: 5.91.0 version: 5.91.0(webpack-cli@5.1.4) @@ -323,55 +323,55 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@biomejs/biome@1.7.3': - resolution: {integrity: sha512-ogFQI+fpXftr+tiahA6bIXwZ7CSikygASdqMtH07J2cUzrpjyTMVc9Y97v23c7/tL1xCZhM+W9k4hYIBm7Q6cQ==} + '@biomejs/biome@1.8.0': + resolution: {integrity: sha512-34xcE2z8GWrIz1sCFEmlHT/+4d+SN7YOqqvzlAKXKvaWPRJ2/NUwxPbRsP01P9QODkQ5bvGvc9rpBihmP+7RJQ==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.7.3': - resolution: {integrity: sha512-eDvLQWmGRqrPIRY7AIrkPHkQ3visEItJKkPYSHCscSDdGvKzYjmBJwG1Gu8+QC5ed6R7eiU63LEC0APFBobmfQ==} + '@biomejs/cli-darwin-arm64@1.8.0': + resolution: {integrity: sha512-dBAYzfIJ1JmWigKlWourT3sJ3I60LZPjqNwwlsyFjiv5AV7vPeWlHVVIImV2BpINwNjZQhpXnwDfVnGS4vr7AA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.7.3': - resolution: {integrity: sha512-JXCaIseKRER7dIURsVlAJacnm8SG5I0RpxZ4ya3dudASYUc68WGl4+FEN03ABY3KMIq7hcK1tzsJiWlmXyosZg==} + '@biomejs/cli-darwin-x64@1.8.0': + resolution: {integrity: sha512-ZTTSD0bP0nn9UpRDGQrQNTILcYSj+IkxTYr3CAV64DWBDtQBomlk2oVKWzDaA1LOhpAsTh0giLCbPJaVk2jfMQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.7.3': - resolution: {integrity: sha512-c8AlO45PNFZ1BYcwaKzdt46kYbuP6xPGuGQ6h4j3XiEDpyseRRUy/h+6gxj07XovmyxKnSX9GSZ6nVbZvcVUAw==} + '@biomejs/cli-linux-arm64-musl@1.8.0': + resolution: {integrity: sha512-+ee/pZWsvhDv6eRI00krRNSgAg8DKSxzOv3LUsCjto6N1VzqatTASeQv2HRfG1nitf79rRKM75LkMJbqEfiKww==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@1.7.3': - resolution: {integrity: sha512-phNTBpo7joDFastnmZsFjYcDYobLTx4qR4oPvc9tJ486Bd1SfEVPHEvJdNJrMwUQK56T+TRClOQd/8X1nnjA9w==} + '@biomejs/cli-linux-arm64@1.8.0': + resolution: {integrity: sha512-cx725jTlJS6dskvJJwwCQaaMRBKE2Qss7ukzmx27Rn/DXRxz6tnnBix4FUGPf1uZfwrERkiJlbWM05JWzpvvXg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@1.7.3': - resolution: {integrity: sha512-UdEHKtYGWEX3eDmVWvQeT+z05T9/Sdt2+F/7zmMOFQ7boANeX8pcO6EkJPK3wxMudrApsNEKT26rzqK6sZRTRA==} + '@biomejs/cli-linux-x64-musl@1.8.0': + resolution: {integrity: sha512-VPA4ocrAOak50VYl8gOAVnjuFFDpIUolShntc/aWM0pZfSIMbRucxnrfUfp44EVwayxjK6ruJTR5xEWj93WvDA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@1.7.3': - resolution: {integrity: sha512-vnedYcd5p4keT3iD48oSKjOIRPYcjSNNbd8MO1bKo9ajg3GwQXZLAH+0Cvlr+eMsO67/HddWmscSQwTFrC/uPA==} + '@biomejs/cli-linux-x64@1.8.0': + resolution: {integrity: sha512-cmgmhlD4QUxMhL1VdaNqnB81xBHb3R7huVNyYnPYzP+AykZ7XqJbPd1KcWAszNjUk2AHdx0aLKEBwCOWemxb2g==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@1.7.3': - resolution: {integrity: sha512-unNCDqUKjujYkkSxs7gFIfdasttbDC4+z0kYmcqzRk6yWVoQBL4dNLcCbdnJS+qvVDNdI9rHp2NwpQ0WAdla4Q==} + '@biomejs/cli-win32-arm64@1.8.0': + resolution: {integrity: sha512-J31spvlh39FfRHQacYXxJX9PvTCH/a8+2Jx9D1lxw+LSF0JybqZcw/4JrlFUWUl4kF3yv8AuYUK0sENScc3g9w==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.7.3': - resolution: {integrity: sha512-ZmByhbrnmz/UUFYB622CECwhKIPjJLLPr5zr3edhu04LzbfcOrz16VYeNq5dpO1ADG70FORhAJkaIGdaVBG00w==} + '@biomejs/cli-win32-x64@1.8.0': + resolution: {integrity: sha512-uPHHvu76JC1zYe9zZDcOU9PAg+1MZmPuNgWkb5jljaDeATvzLFPB+0nuJTilf603LXL+E8IdPQAO61Wy2VuEJA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -576,16 +576,20 @@ packages: resolution: {integrity: sha512-PmJPnogldqoVFf+EwbHvbBJ98MmqASV8kLrBYgsDNxQcFMeIS7JFL48sfyXvuMtgmWO/wMhh25odr+8VhDmn4g==} engines: {node: '>=18'} - '@testing-library/react@15.0.7': - resolution: {integrity: sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==} + '@testing-library/react@16.0.0': + resolution: {integrity: sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==} engines: {node: '>=18'} peerDependencies: + '@testing-library/dom': ^10.0.0 '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 react: ^18.0.0 react-dom: ^18.0.0 peerDependenciesMeta: '@types/react': optional: true + '@types/react-dom': + optional: true '@tootallnate/once@2.0.0': resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} @@ -669,8 +673,8 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - '@types/node@20.14.0': - resolution: {integrity: sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==} + '@types/node@20.14.2': + resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} '@types/nprogress@0.2.3': resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} @@ -1016,10 +1020,6 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - builder-util-runtime@9.2.3: - resolution: {integrity: sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==} - engines: {node: '>=12.0.0'} - builder-util-runtime@9.2.4: resolution: {integrity: sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==} engines: {node: '>=12.0.0'} @@ -1362,8 +1362,8 @@ packages: electron-to-chromium@1.4.719: resolution: {integrity: sha512-FbWy2Q2YgdFzkFUW/W5jBjE9dj+804+98E4Pup78JBPnbdb3pv6IneY2JCPKdeKLh3AOKHQeYf+KwLr7mxGh6Q==} - electron-updater@6.1.8: - resolution: {integrity: sha512-hhOTfaFAd6wRHAfUaBhnAOYc+ymSGCWJLtFkw4xJqOvtpHmIdNHnXDV9m1MHC+A6q08Abx4Ykgyz/R5DGKNAMQ==} + electron-updater@6.2.1: + resolution: {integrity: sha512-83eKIPW14qwZqUUM6wdsIRwVKZyjmHxQ4/8G+1C6iS5PdDt7b1umYQyj1/qPpH510GmHEQe4q0kCPe3qmb3a0Q==} electron@30.0.9: resolution: {integrity: sha512-ArxgdGHVu3o5uaP+Tqj8cJDvU03R6vrGrOqiMs7JXLnvQHMqXJIIxmFKQAIdJW8VoT3ac3hD21tA7cPO10RLow==} @@ -3382,39 +3382,39 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@biomejs/biome@1.7.3': + '@biomejs/biome@1.8.0': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.7.3 - '@biomejs/cli-darwin-x64': 1.7.3 - '@biomejs/cli-linux-arm64': 1.7.3 - '@biomejs/cli-linux-arm64-musl': 1.7.3 - '@biomejs/cli-linux-x64': 1.7.3 - '@biomejs/cli-linux-x64-musl': 1.7.3 - '@biomejs/cli-win32-arm64': 1.7.3 - '@biomejs/cli-win32-x64': 1.7.3 - - '@biomejs/cli-darwin-arm64@1.7.3': + '@biomejs/cli-darwin-arm64': 1.8.0 + '@biomejs/cli-darwin-x64': 1.8.0 + '@biomejs/cli-linux-arm64': 1.8.0 + '@biomejs/cli-linux-arm64-musl': 1.8.0 + '@biomejs/cli-linux-x64': 1.8.0 + '@biomejs/cli-linux-x64-musl': 1.8.0 + '@biomejs/cli-win32-arm64': 1.8.0 + '@biomejs/cli-win32-x64': 1.8.0 + + '@biomejs/cli-darwin-arm64@1.8.0': optional: true - '@biomejs/cli-darwin-x64@1.7.3': + '@biomejs/cli-darwin-x64@1.8.0': optional: true - '@biomejs/cli-linux-arm64-musl@1.7.3': + '@biomejs/cli-linux-arm64-musl@1.8.0': optional: true - '@biomejs/cli-linux-arm64@1.7.3': + '@biomejs/cli-linux-arm64@1.8.0': optional: true - '@biomejs/cli-linux-x64-musl@1.7.3': + '@biomejs/cli-linux-x64-musl@1.8.0': optional: true - '@biomejs/cli-linux-x64@1.7.3': + '@biomejs/cli-linux-x64@1.8.0': optional: true - '@biomejs/cli-win32-arm64@1.7.3': + '@biomejs/cli-win32-arm64@1.8.0': optional: true - '@biomejs/cli-win32-x64@1.7.3': + '@biomejs/cli-win32-x64@1.8.0': optional: true '@cspotcode/source-map-support@0.8.1': @@ -3513,27 +3513,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -3558,7 +3558,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -3576,7 +3576,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.0 + '@types/node': 20.14.2 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3598,7 +3598,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.0 + '@types/node': 20.14.2 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -3668,7 +3668,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -3760,15 +3760,15 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/react@15.0.7(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react@16.0.0(@testing-library/dom@10.0.0)(@types/react-dom@18.2.22)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.1 '@testing-library/dom': 10.0.0 - '@types/react-dom': 18.2.22 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.3 + '@types/react-dom': 18.2.22 '@tootallnate/once@2.0.0': {} @@ -3807,7 +3807,7 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/responselike': 1.0.3 '@types/debug@4.1.12': @@ -3828,11 +3828,11 @@ snapshots: '@types/fs-extra@9.0.13': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/history@4.7.11': {} @@ -3855,7 +3855,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 @@ -3863,11 +3863,11 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/ms@0.7.34': {} - '@types/node@20.14.0': + '@types/node@20.14.2': dependencies: undici-types: 5.26.5 @@ -3875,7 +3875,7 @@ snapshots: '@types/plist@3.0.5': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 xmlbuilder: 15.1.1 optional: true @@ -3884,6 +3884,7 @@ snapshots: '@types/react-dom@18.2.22': dependencies: '@types/react': 18.3.3 + optional: true '@types/react-router-dom@5.3.3': dependencies: @@ -3907,7 +3908,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 '@types/stack-utils@2.0.3': {} @@ -3924,7 +3925,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 optional: true '@webassemblyjs/ast@1.12.1': @@ -4313,13 +4314,6 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - builder-util-runtime@9.2.3: - dependencies: - debug: 4.3.4 - sax: 1.3.0 - transitivePeerDependencies: - - supports-color - builder-util-runtime@9.2.4: dependencies: debug: 4.3.4 @@ -4501,13 +4495,13 @@ snapshots: buffer: 5.7.1 optional: true - create-jest@29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)): + create-jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -4699,9 +4693,9 @@ snapshots: electron-to-chromium@1.4.719: {} - electron-updater@6.1.8: + electron-updater@6.2.1: dependencies: - builder-util-runtime: 9.2.3 + builder-util-runtime: 9.2.4 fs-extra: 10.1.0 js-yaml: 4.1.0 lazy-val: 1.0.5 @@ -4715,7 +4709,7 @@ snapshots: electron@30.0.9: dependencies: '@electron/get': 2.0.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 extract-zip: 2.0.1 transitivePeerDependencies: - supports-color @@ -5218,7 +5212,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -5238,16 +5232,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)): + jest-cli@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + create-jest: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -5257,7 +5251,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: '@babel/core': 7.24.3 '@jest/test-sequencer': 29.7.0 @@ -5282,8 +5276,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.0 - ts-node: 10.9.2(@types/node@20.14.0)(typescript@5.4.5) + '@types/node': 20.14.2 + ts-node: 10.9.2(@types/node@20.14.2)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -5313,7 +5307,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.14.0 + '@types/node': 20.14.2 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -5327,7 +5321,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -5337,7 +5331,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.0 + '@types/node': 20.14.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -5376,7 +5370,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -5411,7 +5405,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -5439,7 +5433,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -5485,7 +5479,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5504,7 +5498,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.0 + '@types/node': 20.14.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -5513,23 +5507,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.0 + '@types/node': 20.14.2 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)): + jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + jest-cli: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -5874,13 +5868,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.38 - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)): + postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: lilconfig: 3.1.1 yaml: 2.4.1 optionalDependencies: postcss: 8.4.38 - ts-node: 10.9.2(@types/node@20.14.0)(typescript@5.4.5) + ts-node: 10.9.2(@types/node@20.14.2)(typescript@5.4.5) postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0(webpack-cli@5.1.4)): dependencies: @@ -6301,7 +6295,7 @@ snapshots: symbol-tree@3.2.4: {} - tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)): + tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -6320,7 +6314,7 @@ snapshots: postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) postcss-nested: 6.0.1(postcss@8.4.38) postcss-selector-parser: 6.0.16 resolve: 1.22.8 @@ -6415,11 +6409,11 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.1.4(@babel/core@7.24.3)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.3))(jest@29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.1.4(@babel/core@7.24.3)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.3))(jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.0)(ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -6443,14 +6437,14 @@ snapshots: typescript: 5.4.5 webpack: 5.91.0(webpack-cli@5.1.4) - ts-node@10.9.2(@types/node@20.14.0)(typescript@5.4.5): + ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.0 + '@types/node': 20.14.2 acorn: 8.11.3 acorn-walk: 8.3.2 arg: 4.1.3 diff --git a/src/__mocks__/state-mocks.ts b/src/__mocks__/state-mocks.ts index da9091ec5..1a1fd0553 100644 --- a/src/__mocks__/state-mocks.ts +++ b/src/__mocks__/state-mocks.ts @@ -79,4 +79,5 @@ export const mockSettings: SettingsState = { markAsDoneOnOpen: false, showAccountHostname: false, delayNotificationState: false, + showPills: true, }; diff --git a/src/components/NotificationRow.test.tsx b/src/components/NotificationRow.test.tsx index 1f9e6f0c8..515386923 100644 --- a/src/components/NotificationRow.test.tsx +++ b/src/components/NotificationRow.test.tsx @@ -26,7 +26,11 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); @@ -43,7 +47,11 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); @@ -60,11 +68,42 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); describe('notification pills / metrics', () => { + describe('showPills disabled', () => { + it('should not render any pills when showPills is disabled', async () => { + jest + .spyOn(global.Date, 'now') + .mockImplementation(() => new Date('2024').valueOf()); + + const mockNotification = mockSingleNotification; + mockNotification.subject.linkedIssues = ['#1']; + + const props = { + notification: mockNotification, + hostname: 'github.com', + }; + + const tree = render( + + + , + ); + expect(tree).toMatchSnapshot(); + }); + }); + describe('linked issue pills', () => { it('should render issues pill when linked to one issue/pr', async () => { jest @@ -79,7 +118,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); @@ -96,7 +143,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); }); @@ -115,7 +170,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); @@ -132,7 +195,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); @@ -149,7 +220,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); }); @@ -168,7 +247,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); }); @@ -190,7 +277,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); @@ -210,7 +305,15 @@ describe('components/NotificationRow.tsx', () => { hostname: 'github.com', }; - const tree = render(); + const tree = render( + + + , + ); expect(tree).toMatchSnapshot(); }); }); @@ -304,12 +407,10 @@ describe('components/NotificationRow.tsx', () => { - - - + , ); @@ -327,14 +428,9 @@ describe('components/NotificationRow.tsx', () => { render( - - - + , ); @@ -352,7 +448,9 @@ describe('components/NotificationRow.tsx', () => { render( - + , diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx index 1ff46aa17..f4f726a37 100644 --- a/src/components/NotificationRow.tsx +++ b/src/components/NotificationRow.tsx @@ -115,129 +115,126 @@ export const NotificationRow: FC = ({ notification, hostname }) => {
openNotification()} onKeyDown={() => openNotification()} >
{notification.subject.title}
-
- - - {notification.subject.user ? ( - - {`${notification.subject.user.login}'s - - ) : ( - - - - )} - - {reason.title} +
+ + {notification.subject.user ? ( + + {`${notification.subject.user.login}'s - {updatedAt} - {notification.subject?.linkedIssues?.length > 0 && ( - - - - )} - {notification.subject.reviews - ? notification.subject.reviews.map((review) => { - const icon = getPullRequestReviewIcon(review); - if (!icon) { - return null; - } - - return ( - - - - ); - }) - : null} - {notification.subject?.comments > 0 && ( - - - - )} - {notification.subject?.labels?.length > 0 && ( - - - - )} - {notification.subject.milestone && ( - - + + )} + {notification.subject.reviews + ? notification.subject.reviews.map((review) => { + const icon = getPullRequestReviewIcon(review); + if (!icon) { + return null; } - aria-label={notification.subject.milestone.title} - /> - - - )} - + + return ( + + + + ); + }) + : null} + {notification.subject?.comments > 0 && ( + + + + )} + {notification.subject?.labels?.length > 0 && ( + + + + )} + {notification.subject.milestone && ( + + + + )} + + )}
diff --git a/src/components/__snapshots__/NotificationRow.test.tsx.snap b/src/components/__snapshots__/NotificationRow.test.tsx.snap index 1829920b0..7cf6e5b80 100644 --- a/src/components/__snapshots__/NotificationRow.test.tsx.snap +++ b/src/components/__snapshots__/NotificationRow.test.tsx.snap @@ -33,58 +33,54 @@ exports[`components/NotificationRow.tsx notification pills / metrics comment pil
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
- - + gitify-app's avatar - - - Updated - - - over 6 years ago - - - - - - - + - -
-
+ + Updated + + + over 6 years ago + + +
+
@@ -4892,52 +4727,439 @@ exports[`components/NotificationRow.tsx should render itself & its children 1`]
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + +
+
+
+ + + +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`components/NotificationRow.tsx should render itself & its children 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+
+ + + + +
+
+
+ I am a robot and this is a test! +
+
+ gitify-app's avatar Updated + + over 6 years ago + - over 6 years ago + + + + + + + +
+
+
+ + + +
+
+
+ , + "container":
+
+
+ + + + +
+
+
+ I am a robot and this is a test! +
+
+ + + gitify-app's avatar + + + Updated + + + over 6 years ago + +
I am a robot and this is a test!
+ gitify-app's avatar + + + Updated + + + over 6 years ago + + - gitify-app's avatar - - - Updated - - - over 6 years ago - -
I am a robot and this is a test!
+ gitify-app's avatar + + + Updated + + + over 6 years ago + + - gitify-app's avatar - - - Updated - - - over 6 years ago - -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago -
I am a robot and this is a test!
+ + + + Updated + + + over 6 years ago + + - - - - - Updated - - - over 6 years ago - - for more details. -
+ See + + for more details.
} /> @@ -197,11 +239,9 @@ export const SettingsRoute: FC = () => { } tooltip={
-
- Keep the notification within Gitify window upon interaction - (click, mark as read, mark as done, etc) until the next - refresh window (scheduled or user initiated) -
+ Keep the notification within Gitify window upon interaction + (click, mark as read, mark as done, etc) until the next refresh + window (scheduled or user initiated)
} /> diff --git a/src/routes/__snapshots__/Settings.test.tsx.snap b/src/routes/__snapshots__/Settings.test.tsx.snap index 4e8b02920..4bf0d4b0f 100644 --- a/src/routes/__snapshots__/Settings.test.tsx.snap +++ b/src/routes/__snapshots__/Settings.test.tsx.snap @@ -171,6 +171,54 @@ exports[`routes/Settings.tsx General should render itself & its children 1`] = `
+
+
+
+ +
+
+ +
+
+
diff --git a/src/types.ts b/src/types.ts index a3e62104f..b9688f535 100644 --- a/src/types.ts +++ b/src/types.ts @@ -41,6 +41,7 @@ interface AppearanceSettingsState { theme: Theme; detailedNotifications: boolean; showAccountHostname: boolean; + showPills: boolean; } interface NotificationSettingsState { diff --git a/src/utils/constants.ts b/src/utils/constants.ts index a7295819e..bb1567670 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -25,7 +25,7 @@ export const Constants = { READ_CLASS_NAME: 'opacity-50 dark:opacity-50', PILL_CLASS_NAME: - 'rounded-full text-xs px-2 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700', + 'rounded-full text-xs px-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700', // GitHub Docs GITHUB_DOCS: {