Skip to content

Commit 0efd2cc

Browse files
committed
feat: hotkeys
Signed-off-by: Adam Setch <adam.setch@outlook.com>
1 parent cd9b3b8 commit 0efd2cc

6 files changed

Lines changed: 848 additions & 51 deletions

File tree

‎src/renderer/App.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export const App = () => {
4141
<ThemeProvider>
4242
<BaseStyles>
4343
<AppProvider>
44-
<GlobalShortcuts />
4544
<Router>
45+
<GlobalShortcuts />
4646
<AppLayout>
4747
<Routes>
4848
<Route

‎src/renderer/components/GlobalShortcuts.test.tsx‎

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { MemoryRouter } from 'react-router-dom';
44
import { renderWithAppContext } from '../__helpers__/test-utils';
55

66
import * as comms from '../utils/comms';
7+
import * as links from '../utils/links';
78
import { GlobalShortcuts } from './GlobalShortcuts';
89

910
const navigateMock = jest.fn();
@@ -22,6 +23,20 @@ describe('components/GlobalShortcuts.tsx', () => {
2223
});
2324

2425
describe('key bindings', () => {
26+
describe('ignores keys that are not valid', () => {
27+
it('ignores B key', async () => {
28+
renderWithAppContext(
29+
<MemoryRouter>
30+
<GlobalShortcuts />
31+
</MemoryRouter>,
32+
);
33+
34+
await userEvent.keyboard('b');
35+
36+
expect(navigateMock).not.toHaveBeenCalled();
37+
});
38+
});
39+
2540
describe('home', () => {
2641
it('navigates home when pressing H key', async () => {
2742
renderWithAppContext(
@@ -36,6 +51,42 @@ describe('components/GlobalShortcuts.tsx', () => {
3651
});
3752
});
3853

54+
describe('openGitHubNotifications', () => {
55+
const openGitHubNotificationsSpy = jest
56+
.spyOn(links, 'openGitHubNotifications')
57+
.mockImplementation();
58+
59+
it('opens primary account GitHub notifications webpage when pressing N while logged in', async () => {
60+
renderWithAppContext(
61+
<MemoryRouter>
62+
<GlobalShortcuts />
63+
</MemoryRouter>,
64+
{
65+
isLoggedIn: true,
66+
},
67+
);
68+
69+
await userEvent.keyboard('n');
70+
71+
expect(openGitHubNotificationsSpy).toHaveBeenCalledTimes(1);
72+
});
73+
74+
it('does not open primary account GitHub notifications webpage when logged out', async () => {
75+
renderWithAppContext(
76+
<MemoryRouter>
77+
<GlobalShortcuts />
78+
</MemoryRouter>,
79+
{
80+
isLoggedIn: false,
81+
},
82+
);
83+
84+
await userEvent.keyboard('n');
85+
86+
expect(openGitHubNotificationsSpy).not.toHaveBeenCalled();
87+
});
88+
});
89+
3990
describe('focus mode', () => {
4091
it('toggles focus when pressing W while logged in', async () => {
4192
renderWithAppContext(
@@ -119,6 +170,78 @@ describe('components/GlobalShortcuts.tsx', () => {
119170
});
120171
});
121172

173+
describe('openGitHubIssues', () => {
174+
const openGitHubIssuesSpy = jest
175+
.spyOn(links, 'openGitHubIssues')
176+
.mockImplementation();
177+
178+
it('opens primary account GitHub issues webpage when pressing I while logged in', async () => {
179+
renderWithAppContext(
180+
<MemoryRouter>
181+
<GlobalShortcuts />
182+
</MemoryRouter>,
183+
{
184+
isLoggedIn: true,
185+
},
186+
);
187+
188+
await userEvent.keyboard('i');
189+
190+
expect(openGitHubIssuesSpy).toHaveBeenCalledTimes(1);
191+
});
192+
193+
it('does not open primary account GitHub issues webpage when logged out', async () => {
194+
renderWithAppContext(
195+
<MemoryRouter>
196+
<GlobalShortcuts />
197+
</MemoryRouter>,
198+
{
199+
isLoggedIn: false,
200+
},
201+
);
202+
203+
await userEvent.keyboard('n');
204+
205+
expect(openGitHubIssuesSpy).not.toHaveBeenCalled();
206+
});
207+
});
208+
209+
describe('openGitHubPulls', () => {
210+
const openGitHubPullsSpy = jest
211+
.spyOn(links, 'openGitHubPulls')
212+
.mockImplementation();
213+
214+
it('opens primary account GitHub pull requests webpage when pressing N while logged in', async () => {
215+
renderWithAppContext(
216+
<MemoryRouter>
217+
<GlobalShortcuts />
218+
</MemoryRouter>,
219+
{
220+
isLoggedIn: true,
221+
},
222+
);
223+
224+
await userEvent.keyboard('p');
225+
226+
expect(openGitHubPullsSpy).toHaveBeenCalledTimes(1);
227+
});
228+
229+
it('does not open primary account GitHub pull requests webpage when logged out', async () => {
230+
renderWithAppContext(
231+
<MemoryRouter>
232+
<GlobalShortcuts />
233+
</MemoryRouter>,
234+
{
235+
isLoggedIn: false,
236+
},
237+
);
238+
239+
await userEvent.keyboard('n');
240+
241+
expect(openGitHubPullsSpy).not.toHaveBeenCalled();
242+
});
243+
});
244+
122245
describe('refresh', () => {
123246
it('refreshes notifications when pressing R key', async () => {
124247
renderWithAppContext(

‎src/renderer/components/Sidebar.tsx‎

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ import { APPLICATION } from '../../shared/constants';
1818
import { useAppContext } from '../hooks/useAppContext';
1919
import { useShortcutActions } from '../hooks/useShortcutActions';
2020

21-
import { getPrimaryAccountHostname } from '../utils/auth/utils';
22-
import {
23-
openGitHubIssues,
24-
openGitHubNotifications,
25-
openGitHubPulls,
26-
} from '../utils/links';
2721
import { hasActiveFilters } from '../utils/notifications/filters/filter';
2822
import { LogoIcon } from './icons/LogoIcon';
2923

@@ -32,13 +26,10 @@ export const Sidebar: FC = () => {
3226
status,
3327
isLoggedIn,
3428
settings,
35-
auth,
3629
notificationCount,
3730
hasUnreadNotifications,
3831
} = useAppContext();
3932

40-
const primaryAccountHostname = getPrimaryAccountHostname(auth);
41-
4233
const { shortcuts } = useShortcutActions();
4334

4435
const isLoading = status === 'loading';
@@ -72,7 +63,8 @@ export const Sidebar: FC = () => {
7263
data-testid="sidebar-notifications"
7364
description={`${notificationCount} ${settings.fetchReadNotifications ? 'notifications' : 'unread notifications'} ↗`}
7465
icon={BellIcon}
75-
onClick={() => openGitHubNotifications(primaryAccountHostname)}
66+
keybindingHint={shortcuts.myNotifications.key}
67+
onClick={() => shortcuts.myNotifications.action()}
7668
size="small"
7769
tooltipDirection="e"
7870
variant={hasUnreadNotifications ? 'primary' : 'invisible'}
@@ -114,7 +106,8 @@ export const Sidebar: FC = () => {
114106
aria-label="My issues ↗"
115107
data-testid="sidebar-my-issues"
116108
icon={IssueOpenedIcon}
117-
onClick={() => openGitHubIssues(primaryAccountHostname)}
109+
keybindingHint={shortcuts.myIssues.key}
110+
onClick={() => shortcuts.myIssues.action()}
118111
size="small"
119112
tooltipDirection="e"
120113
variant="invisible"
@@ -124,7 +117,8 @@ export const Sidebar: FC = () => {
124117
aria-label="My pull requests ↗"
125118
data-testid="sidebar-my-pull-requests"
126119
icon={GitPullRequestIcon}
127-
onClick={() => openGitHubPulls(primaryAccountHostname)}
120+
keybindingHint={shortcuts.myPullRequests.key}
121+
onClick={() => shortcuts.myPullRequests.action()}
128122
size="small"
129123
tooltipDirection="e"
130124
variant="invisible"

0 commit comments

Comments
 (0)