diff --git a/src/__mocks__/state-mocks.ts b/src/__mocks__/state-mocks.ts index 12b3f638e..1c15adcd7 100644 --- a/src/__mocks__/state-mocks.ts +++ b/src/__mocks__/state-mocks.ts @@ -87,6 +87,7 @@ const mockNotificationSettings = { groupBy: GroupBy.REPOSITORY, participating: false, markAsDoneOnOpen: false, + markAsDoneOnUnsubscribe: false, delayNotificationState: false, }; diff --git a/src/components/settings/NotificationSettings.test.tsx b/src/components/settings/NotificationSettings.test.tsx index 6cfbd1f8a..7b740125f 100644 --- a/src/components/settings/NotificationSettings.test.tsx +++ b/src/components/settings/NotificationSettings.test.tsx @@ -123,6 +123,34 @@ describe('routes/components/settings/NotificationSettings.tsx', () => { expect(updateSetting).toHaveBeenCalledWith('markAsDoneOnOpen', false); }); + it('should toggle the markAsDoneOnUnsubscribe checkbox', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + fireEvent.click(screen.getByLabelText('Mark as done on unsubscribe'), { + target: { checked: true }, + }); + + expect(updateSetting).toHaveBeenCalledTimes(1); + expect(updateSetting).toHaveBeenCalledWith( + 'markAsDoneOnUnsubscribe', + false, + ); + }); + it('should toggle the delayNotificationState checkbox', async () => { await act(async () => { render( diff --git a/src/components/settings/NotificationSettings.tsx b/src/components/settings/NotificationSettings.tsx index 1a7096285..329ea9994 100644 --- a/src/components/settings/NotificationSettings.tsx +++ b/src/components/settings/NotificationSettings.tsx @@ -63,6 +63,20 @@ export const NotificationSettings: FC = () => { } /> + + updateSetting('markAsDoneOnUnsubscribe', evt.target.checked) + } + tooltip={ +
+ Mark as Done feature is supported in GitHub Cloud + and GitHub Enterprise Server 3.13 or later. +
+ } + /> { theme: 'SYSTEM', detailedNotifications: true, markAsDoneOnOpen: false, + markAsDoneOnUnsubscribe: false, showAccountHeader: false, delayNotificationState: false, showPills: true, @@ -411,6 +412,7 @@ describe('context/App.tsx', () => { theme: 'SYSTEM', detailedNotifications: true, markAsDoneOnOpen: false, + markAsDoneOnUnsubscribe: false, showAccountHeader: false, delayNotificationState: false, showPills: true, diff --git a/src/context/App.tsx b/src/context/App.tsx index eb93a8e91..beb1e3f14 100644 --- a/src/context/App.tsx +++ b/src/context/App.tsx @@ -67,6 +67,7 @@ const defaultNotificationSettings = { groupBy: GroupBy.REPOSITORY, participating: false, markAsDoneOnOpen: false, + markAsDoneOnUnsubscribe: false, delayNotificationState: false, }; diff --git a/src/hooks/useNotifications.test.ts b/src/hooks/useNotifications.test.ts index 1b014a122..db634a254 100644 --- a/src/hooks/useNotifications.test.ts +++ b/src/hooks/useNotifications.test.ts @@ -426,7 +426,7 @@ describe('hooks/useNotifications.ts', () => { describe('unsubscribeNotification', () => { const id = 'notification-123'; - it('should unsubscribe from a notification with success', async () => { + it('should unsubscribe from a notification with success - markAsDoneOnUnsubscribe = false', async () => { // The unsubscribe endpoint call. nock('https://api.github.com/') .put(`/notifications/threads/${id}/subscription`) @@ -453,6 +453,39 @@ describe('hooks/useNotifications.ts', () => { expect(result.current.notifications.length).toBe(0); }); + it('should unsubscribe from a notification with success - markAsDoneOnUnsubscribe = true', async () => { + // The unsubscribe endpoint call. + nock('https://api.github.com/') + .put(`/notifications/threads/${id}/subscription`) + .reply(200); + + // The mark done endpoint call. + nock('https://api.github.com/') + .delete(`/notifications/threads/${id}`) + .reply(200); + + const { result } = renderHook(() => useNotifications()); + + act(() => { + result.current.unsubscribeNotification( + { + ...mockState, + settings: { + ...mockState.settings, + markAsDoneOnUnsubscribe: true, + }, + }, + mockSingleNotification, + ); + }); + + await waitFor(() => { + expect(result.current.status).toBe('success'); + }); + + expect(result.current.notifications.length).toBe(0); + }); + it('should unsubscribe from a notification with failure', async () => { // The unsubscribe endpoint call. nock('https://api.github.com/') diff --git a/src/hooks/useNotifications.ts b/src/hooks/useNotifications.ts index c5dd9b111..e732aa0ba 100644 --- a/src/hooks/useNotifications.ts +++ b/src/hooks/useNotifications.ts @@ -176,7 +176,12 @@ export const useNotifications = (): NotificationsState => { notification.account.hostname, notification.account.token, ); - await markNotificationRead(state, notification); + + if (state.settings.markAsDoneOnUnsubscribe) { + await markNotificationDone(state, notification); + } else { + await markNotificationRead(state, notification); + } } catch (err) { log.error( 'Error occurred while unsubscribing from notification thread', diff --git a/src/routes/__snapshots__/Settings.test.tsx.snap b/src/routes/__snapshots__/Settings.test.tsx.snap index 74818bec6..90effae09 100644 --- a/src/routes/__snapshots__/Settings.test.tsx.snap +++ b/src/routes/__snapshots__/Settings.test.tsx.snap @@ -513,6 +513,49 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = ` +
+
+ +
+ +
+
+
diff --git a/src/types.ts b/src/types.ts index d21ffb95f..f7c1bea00 100644 --- a/src/types.ts +++ b/src/types.ts @@ -78,6 +78,7 @@ interface NotificationSettingsState { participating: boolean; showNotifications: boolean; markAsDoneOnOpen: boolean; + markAsDoneOnUnsubscribe: boolean; delayNotificationState: boolean; groupBy: GroupBy; }