Skip to content

Commit 1e1adde

Browse files
authored
feat: add "Mark as done on open" setting (#746)
* feat: add button to mark a notification as done * tests: add tests for `markNotificationDone()` * feat: update "mark notification as read" icon * tests: update snaps * fix: remove now obsolete `markOnClick` * feat: add "Mark as done on open" setting
1 parent cfaf623 commit 1e1adde

File tree

9 files changed

+95
-2
lines changed

9 files changed

+95
-2
lines changed

src/__mocks__/mock-state.ts

+1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ export const mockSettings: SettingsState = {
1919
openAtStartup: false,
2020
appearance: Appearance.SYSTEM,
2121
colors: false,
22+
markAsDoneOnOpen: false,
2223
};

src/components/NotificationRow.test.tsx

+27-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ describe('components/Notification.js', () => {
4141
const { getByRole } = render(
4242
<AppContext.Provider
4343
value={{
44-
settings: mockSettings,
44+
settings: { ...mockSettings, markAsDoneOnOpen: false },
4545
markNotification,
4646
accounts: mockAccounts,
4747
}}
@@ -54,6 +54,31 @@ describe('components/Notification.js', () => {
5454
expect(shell.openExternal).toHaveBeenCalledTimes(1);
5555
});
5656

57+
it('should open a notification in browser & mark it as done', () => {
58+
const markNotificationDone = jest.fn();
59+
60+
const props = {
61+
notification: mockedSingleNotification,
62+
hostname: 'github.com',
63+
};
64+
65+
const { getByRole } = render(
66+
<AppContext.Provider
67+
value={{
68+
settings: { ...mockSettings, markAsDoneOnOpen: true },
69+
markNotificationDone,
70+
accounts: mockAccounts,
71+
}}
72+
>
73+
<NotificationRow {...props} />
74+
</AppContext.Provider>,
75+
);
76+
77+
fireEvent.click(getByRole('main'));
78+
expect(shell.openExternal).toHaveBeenCalledTimes(1);
79+
expect(markNotificationDone).toHaveBeenCalledTimes(1);
80+
});
81+
5782
it('should mark a notification as read', () => {
5883
const markNotification = jest.fn();
5984

@@ -65,7 +90,7 @@ describe('components/Notification.js', () => {
6590
const { getByTitle } = render(
6691
<AppContext.Provider
6792
value={{
68-
settings: mockSettings,
93+
settings: { ...mockSettings, markAsDoneOnOpen: false },
6994
accounts: mockAccounts,
7095
}}
7196
>

src/components/NotificationRow.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export const NotificationRow: React.FC<IProps> = ({
3030

3131
const pressTitle = useCallback(() => {
3232
openBrowser();
33+
34+
if (settings.markAsDoneOnOpen) {
35+
markNotificationDone(notification.id, hostname);
36+
}
3337
}, [settings]);
3438

3539
const openBrowser = useCallback(

src/context/App.test.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ describe('context/App.tsx', () => {
291291
playSound: true,
292292
showNotifications: true,
293293
colors: false,
294+
markAsDoneOnOpen: false,
294295
},
295296
);
296297
});
@@ -328,6 +329,7 @@ describe('context/App.tsx', () => {
328329
playSound: true,
329330
showNotifications: true,
330331
colors: false,
332+
markAsDoneOnOpen: false,
331333
},
332334
);
333335
});

src/context/App.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const defaultSettings: SettingsState = {
3737
openAtStartup: false,
3838
appearance: Appearance.SYSTEM,
3939
colors: false,
40+
markAsDoneOnOpen: false,
4041
};
4142

4243
interface AppContextState {

src/routes/Settings.test.tsx

+28
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,34 @@ describe('routes/Settings.tsx', () => {
182182
expect(updateSetting).toHaveBeenCalledWith('showNotifications', false);
183183
});
184184

185+
it('should toggle the markAsDoneOnOpen checkbox', async () => {
186+
let getByLabelText;
187+
188+
await act(async () => {
189+
const { getByLabelText: getByLabelTextLocal } = render(
190+
<AppContext.Provider
191+
value={{
192+
settings: mockSettings,
193+
accounts: mockAccounts,
194+
updateSetting,
195+
}}
196+
>
197+
<MemoryRouter>
198+
<SettingsRoute />
199+
</MemoryRouter>
200+
</AppContext.Provider>,
201+
);
202+
getByLabelText = getByLabelTextLocal;
203+
});
204+
205+
fireEvent.click(getByLabelText('Mark as done on open'), {
206+
target: { checked: true },
207+
});
208+
209+
expect(updateSetting).toHaveBeenCalledTimes(1);
210+
expect(updateSetting).toHaveBeenCalledWith('markAsDoneOnOpen', false);
211+
});
212+
185213
it('should toggle the openAtStartup checkbox', async () => {
186214
let getByLabelText;
187215

src/routes/Settings.tsx

+8
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ export const SettingsRoute: React.FC = () => {
139139
updateSetting('showNotifications', evt.target.checked)
140140
}
141141
/>
142+
<FieldCheckbox
143+
name="markAsDoneOnOpen"
144+
label="Mark as done on open"
145+
checked={settings.markAsDoneOnOpen}
146+
onChange={(evt) =>
147+
updateSetting('markAsDoneOnOpen', evt.target.checked)
148+
}
149+
/>
142150
{!isLinux && (
143151
<FieldCheckbox
144152
name="openAtStartUp"

src/routes/__snapshots__/Settings.test.tsx.snap

+23
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,29 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
230230
</label>
231231
</div>
232232
</div>
233+
<div
234+
class="flex items-start mt-1 mb-3"
235+
>
236+
<div
237+
class="flex items-center h-5"
238+
>
239+
<input
240+
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
241+
id="markAsDoneOnOpen"
242+
type="checkbox"
243+
/>
244+
</div>
245+
<div
246+
class="ml-3 text-sm"
247+
>
248+
<label
249+
class="font-medium text-gray-700 dark:text-gray-200"
250+
for="markAsDoneOnOpen"
251+
>
252+
Mark as done on open
253+
</label>
254+
</div>
255+
</div>
233256
<div
234257
class="flex items-start mt-1 mb-3"
235258
>

src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface SettingsState {
1313
openAtStartup: boolean;
1414
appearance: Appearance;
1515
colors: boolean;
16+
markAsDoneOnOpen: boolean;
1617
}
1718

1819
export enum Appearance {

0 commit comments

Comments
 (0)