Repository: gitify-app/gitify
Pull request #1005 (2024-04-14 11:59:45)

refactor: generalize color setting and skip detailed subject fetching when disabled
Rename the existing `colors` settings to a more general `detailedNotifications`.

When set to false, skip fetching detailed subject info for each notification (help avoid rate-limiting).

Note: I have used this setting as the example within https://github.com/gitify-app/gitify/pull/1006 


Patch:
diff --git a/src/__mocks__/mock-state.ts b/src/__mocks__/mock-state.ts
index 9624e91a..01cb113a 100644
--- a/src/__mocks__/mock-state.ts
+++ b/src/__mocks__/mock-state.ts
@@ -15,7 +15,7 @@ export const mockSettings: SettingsState = {
   showNotificationsCountInTray: false,
   openAtStartup: false,
   theme: Theme.SYSTEM,
-  colors: false,
+  detailedNotifications: false,
   markAsDoneOnOpen: false,
   showAccountHostname: false,
 };
diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx
index 58e7fe31..79b2449b 100644
--- a/src/components/NotificationRow.tsx
+++ b/src/components/NotificationRow.tsx
@@ -73,9 +73,6 @@ export const NotificationRow: FC<IProps> = ({ notification, hostname }) => {
   const reason = formatReason(notification.reason);
   const NotificationIcon = getNotificationTypeIcon(notification.subject);
   const iconColor = getNotificationTypeIconColor(notification.subject);
-  const realIconColor = settings
-    ? (settings.colors && iconColor) || ''
-    : iconColor;
   const updatedAt = formatDistanceToNow(parseISO(notification.updated_at), {
     addSuffix: true,
   });
@@ -91,7 +88,7 @@ export const NotificationRow: FC<IProps> = ({ notification, hostname }) => {
   return (
     <div className="flex space-x-3 py-2 px-3 bg-white dark:bg-gray-dark dark:text-white hover:bg-gray-100 dark:hover:bg-gray-darker border-b border-gray-100 dark:border-gray-darker group">
       <div
-        className={`flex justify-center items-center w-5 ${realIconColor}`}
+        className={`flex justify-center items-center w-5 ${iconColor}`}
         title={notificationTitle}
       >
         <NotificationIcon size={18} aria-label={notification.subject.type} />
diff --git a/src/components/fields/FieldInput.tsx b/src/components/fields/FieldInput.tsx
index 47fcd83f..c70ae2e2 100644
--- a/src/components/fields/FieldInput.tsx
+++ b/src/components/fields/FieldInput.tsx
@@ -21,7 +21,7 @@ export const FieldInput: FC<IFieldInput> = ({
   return (
     <Field name={name}>
       {({ input, meta: { touched, error } }) => (
-        <div className="mt-2">
+        <div className="mb-4">
           <label
             className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
             htmlFor={input.name}
diff --git a/src/context/App.tsx b/src/context/App.tsx
index 5023eb20..4e2e6b77 100644
--- a/src/context/App.tsx
+++ b/src/context/App.tsx
@@ -41,7 +41,7 @@ export const defaultSettings: SettingsState = {
   showNotificationsCountInTray: false,
   openAtStartup: false,
   theme: Theme.SYSTEM,
-  colors: null,
+  detailedNotifications: false,
   markAsDoneOnOpen: false,
   showAccountHostname: false,
 };
@@ -90,7 +90,7 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
     unsubscribeNotification,
     markRepoNotifications,
     markRepoNotificationsDone,
-  } = useNotifications(settings.colors);
+  } = useNotifications();
 
   useEffect(() => {
     restoreSettings();
@@ -100,14 +100,21 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
     setTheme(settings.theme as Theme);
   }, [settings.theme]);
 
+  // biome-ignore lint/correctness/useExhaustiveDependencies: We only want fetchNotifications to be called for a subset of settings changes.
   useEffect(() => {
     fetchNotifications(accounts, settings);
-  }, [settings.participating, settings.showBots]);
+  }, [
+    settings.participating,
+    settings.showBots,
+    settings.detailedNotifications,
+  ]);
 
+  // biome-ignore lint/correctness/useExhaustiveDependencies: We only want fetchNotifications to be called for certain account changes.
   useEffect(() => {
     fetchNotifications(accounts, settings);
   }, [accounts.token, accounts.enterpriseAccounts.length]);
 
+  // biome-ignore lint/correctness/useExhaustiveDependencies: We need to update tray title when settings or notifications changes.
   useEffect(() => {
     const count = getNotificationCount(notifications);
 
diff --git a/src/hooks/useNotifications.ts b/src/hooks/useNotifications.ts
index a248c75e..f830be06 100644
--- a/src/hooks/useNotifications.ts
+++ b/src/hooks/useNotifications.ts
@@ -62,7 +62,7 @@ interface NotificationsState {
   errorDetails: GitifyError;
 }
 
-export const useNotifications = (colors: boolean): NotificationsState => {
+export const useNotifications = (): NotificationsState => {
   const [isFetching, setIsFetching] = useState(false);
   const [requestFailed, setRequestFailed] = useState(false);
   const [errorDetails, setErrorDetails] = useState<GitifyError>();
@@ -118,6 +118,7 @@ export const useNotifications = (colors: boolean): NotificationsState => {
                 };
               },
             );
+
             const data = isGitHubLoggedIn(accounts)
               ? [
                   ...enterpriseNotifications,
@@ -135,17 +136,6 @@ export const useNotifications = (colors: boolean): NotificationsState => {
                 ]
               : [...enterpriseNotifications];
 
-            if (colors === false) {
-              setNotifications(data);
-              triggerNativeNotifications(
-                notifications,
-                data,
-                settings,
-                accounts,
-              );
-              setIsFetching(false);
-              return;
-            }
             axios
               .all(
                 data.map(async (accountNotifications) => {
@@ -155,6 +145,10 @@ export const useNotifications = (colors: boolean): NotificationsState => {
                       .all<Notification>(
                         accountNotifications.notifications.map(
                           async (notification: Notification) => {
+                            if (!settings.detailedNotifications) {
+                              return notification;
+                            }
+
                             const token = getTokenForHost(
                               notification.hostname,
                               accounts,
diff --git a/src/routes/LoginWithToken.tsx b/src/routes/LoginWithToken.tsx
index 2f05eade..d249190a 100644
--- a/src/routes/LoginWithToken.tsx
+++ b/src/routes/LoginWithToken.tsx
@@ -67,17 +67,17 @@ export const LoginWithToken: FC = () => {
           helpText={
             <div>
               <div>
-                Create a Personal Access Token on GitHub and paste above.
-              </div>
-              <div>
-                The required scopes will be selected for you.{' '}
                 <button
                   type="button"
-                  className={`px-2 py-1 my-2 text-xs ${buttonClasses}`}
+                  className={`px-2 py-1 text-xs ${buttonClasses}`}
                   onClick={() => openLink(getNewTokenURL())}
                 >
                   Generate a PAT
-                </button>
+                </button>{' '}
+                on GitHub and paste above.
+              </div>
+              <div className="italic mt-1">
+                The required scopes will be selected for you.
               </div>
             </div>
           }
@@ -90,7 +90,7 @@ export const LoginWithToken: FC = () => {
           helpText={
             <div>
               <div>Defaults to github.com.</div>
-              <div className="italic">
+              <div className="italic mt-1">
                 Change only if you are using GitHub Enterprise Server.
               </div>
             </div>
diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx
index 5d3afdfa..25a975eb 100644
--- a/src/routes/Settings.tsx
+++ b/src/routes/Settings.tsx
@@ -36,7 +36,7 @@ export const SettingsRoute: FC = () => {
 
   const [isLinux, setIsLinux] = useState<boolean>(false);
   const [appVersion, setAppVersion] = useState<string | null>(null);
-  const [colorScope, setColorScope] = useState<boolean>(false);
+  const [repoScope, setRepoScope] = useState<boolean>(false);
 
   const openGitHubReleaseNotes = useCallback((version) => {
     openExternalLink(
@@ -63,7 +63,7 @@ export const SettingsRoute: FC = () => {
       );
 
       if (response.headers['x-oauth-scopes'].includes('repo'))
-        setColorScope(true);
+        setRepoScope(true);
     })();
   }, [accounts.token]);
 
@@ -132,15 +132,16 @@ export const SettingsRoute: FC = () => {
             }}
           />
           <Checkbox
-            name="colors"
-            label={`Use GitHub-like state colors${
-              !colorScope ? ' (requires repo scope)' : ''
+            name="detailedNotifications"
+            label={`Detailed notifications${
+              !repoScope ? ' (requires repo scope)' : ''
             }`}
-            checked={colorScope && settings.colors}
+            checked={repoScope && settings.detailedNotifications}
             onChange={(evt) =>
-              colorScope && updateSetting('colors', evt.target.checked)
+              repoScope &&
+              updateSetting('detailedNotifications', evt.target.checked)
             }
-            disabled={!colorScope}
+            disabled={!repoScope}
           />
           <Checkbox
             name="showAccountHostname"
@@ -191,7 +192,6 @@ export const SettingsRoute: FC = () => {
             onChange={(evt) =>
               updateSetting('showNotificationsCountInTray', evt.target.checked)
             }
-            helpText="Changes will take effect after restarting the app"
           />
           <Checkbox
             name="showNotifications"
diff --git a/src/types.ts b/src/types.ts
index c53f9dc0..36bb2e01 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -12,7 +12,7 @@ export type SettingsState = AppearanceSettingsState &
 
 interface AppearanceSettingsState {
   theme: Theme;
-  colors: boolean | null;
+  detailedNotifications: boolean;
   showAccountHostname: boolean;
 }
 


Test patch:
diff --git a/src/components/fields/__snapshots__/FieldInput.test.tsx.snap b/src/components/fields/__snapshots__/FieldInput.test.tsx.snap
index b7ba3d9c..59a42119 100644
--- a/src/components/fields/__snapshots__/FieldInput.test.tsx.snap
+++ b/src/components/fields/__snapshots__/FieldInput.test.tsx.snap
@@ -5,7 +5,7 @@ exports[`components/fields/FieldInput.tsx should render 1`] = `
   onSubmit={[Function]}
 >
   <div
-    className="mt-2"
+    className="mb-4"
   >
     <label
       className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
diff --git a/src/context/App.test.tsx b/src/context/App.test.tsx
index cbb3e745..92f38756 100644
--- a/src/context/App.test.tsx
+++ b/src/context/App.test.tsx
@@ -318,7 +318,7 @@ describe('context/App.tsx', () => {
         showNotificationsCountInTray: false,
         openAtStartup: false,
         theme: 'SYSTEM',
-        colors: null,
+        detailedNotifications: false,
         markAsDoneOnOpen: false,
         showAccountHostname: false,
       },
@@ -362,7 +362,7 @@ describe('context/App.tsx', () => {
         showNotificationsCountInTray: false,
         openAtStartup: true,
         theme: 'SYSTEM',
-        colors: null,
+        detailedNotifications: false,
         markAsDoneOnOpen: false,
         showAccountHostname: false,
       },
diff --git a/src/hooks/useNotifications.test.ts b/src/hooks/useNotifications.test.ts
index 0df092ec..2a41d918 100644
--- a/src/hooks/useNotifications.test.ts
+++ b/src/hooks/useNotifications.test.ts
@@ -31,7 +31,7 @@ describe('hooks/useNotifications.ts', () => {
           .get('/notifications?participating=false')
           .reply(200, notifications);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -62,7 +62,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -86,7 +86,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -110,7 +110,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -134,7 +134,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -158,7 +158,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -191,7 +191,7 @@ describe('hooks/useNotifications.ts', () => {
           .get('/notifications?participating=false')
           .reply(200, notifications);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.fetchNotifications(accounts, mockSettings);
@@ -216,7 +216,7 @@ describe('hooks/useNotifications.ts', () => {
           .get('/notifications?participating=false')
           .reply(400, { message: 'Oops! Something went wrong.' });
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.fetchNotifications(accounts, mockSettings);
@@ -245,7 +245,7 @@ describe('hooks/useNotifications.ts', () => {
           .get('/notifications?participating=false')
           .reply(200, notifications);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.fetchNotifications(accounts, mockSettings);
@@ -271,7 +271,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(accounts, mockSettings);
@@ -295,7 +295,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(accounts, mockSettings);
@@ -319,7 +319,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(accounts, mockSettings);
@@ -343,7 +343,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(accounts, mockSettings);
@@ -367,7 +367,7 @@ describe('hooks/useNotifications.ts', () => {
             .get('/notifications?participating=false')
             .reply(status, { message });
 
-          const { result } = renderHook(() => useNotifications(false));
+          const { result } = renderHook(() => useNotifications());
 
           act(() => {
             result.current.fetchNotifications(accounts, mockSettings);
@@ -529,12 +529,12 @@ describe('hooks/useNotifications.ts', () => {
           user: mockedNotificationUser,
         });
 
-        const { result } = renderHook(() => useNotifications(true));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.fetchNotifications(accounts, {
             ...mockSettings,
-            colors: true,
+            detailedNotifications: true,
           });
         });
 
@@ -607,11 +607,12 @@ describe('hooks/useNotifications.ts', () => {
             },
           });
 
-        const { result } = renderHook(() => useNotifications(true));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.fetchNotifications(accounts, {
             ...mockSettings,
+            detailedNotifications: true,
             showBots: false,
           });
         });
@@ -642,7 +643,7 @@ describe('hooks/useNotifications.ts', () => {
         .get('/notifications?participating=false')
         .reply(200, notifications);
 
-      const { result } = renderHook(() => useNotifications(false));
+      const { result } = renderHook(() => useNotifications());
 
       act(() => {
         result.current.fetchNotifications(mockAccounts, mockSettings);
@@ -675,7 +676,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationRead(accounts, id, hostname);
@@ -693,7 +694,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationRead(accounts, id, hostname);
@@ -716,7 +717,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationRead(accounts, id, hostname);
@@ -734,7 +735,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationRead(accounts, id, hostname);
@@ -761,7 +762,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationDone(accounts, id, hostname);
@@ -779,7 +780,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationDone(accounts, id, hostname);
@@ -802,7 +803,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationDone(accounts, id, hostname);
@@ -820,7 +821,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markNotificationDone(accounts, id, hostname);
@@ -853,7 +854,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.unsubscribeNotification(accounts, id, hostname);
@@ -877,7 +878,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.unsubscribeNotification(accounts, id, hostname);
@@ -906,7 +907,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.unsubscribeNotification(accounts, id, hostname);
@@ -930,7 +931,7 @@ describe('hooks/useNotifications.ts', () => {
           .patch(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.unsubscribeNotification(accounts, id, hostname);
@@ -957,7 +958,7 @@ describe('hooks/useNotifications.ts', () => {
           .put(`/repos/${repoSlug}/notifications`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotifications(accounts, repoSlug, hostname);
@@ -975,7 +976,7 @@ describe('hooks/useNotifications.ts', () => {
           .put(`/repos/${repoSlug}/notifications`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotifications(accounts, repoSlug, hostname);
@@ -998,7 +999,7 @@ describe('hooks/useNotifications.ts', () => {
           .put(`/repos/${repoSlug}/notifications`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotifications(accounts, repoSlug, hostname);
@@ -1016,7 +1017,7 @@ describe('hooks/useNotifications.ts', () => {
           .put(`/repos/${repoSlug}/notifications`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotifications(accounts, repoSlug, hostname);
@@ -1044,7 +1045,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotificationsDone(
@@ -1066,7 +1067,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotificationsDone(
@@ -1093,7 +1094,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(200);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotificationsDone(
@@ -1115,7 +1116,7 @@ describe('hooks/useNotifications.ts', () => {
           .delete(`/notifications/threads/${id}`)
           .reply(400);
 
-        const { result } = renderHook(() => useNotifications(false));
+        const { result } = renderHook(() => useNotifications());
 
         act(() => {
           result.current.markRepoNotificationsDone(
diff --git a/src/routes/Settings.test.tsx b/src/routes/Settings.test.tsx
index eefc923b..afee0c47 100644
--- a/src/routes/Settings.test.tsx
+++ b/src/routes/Settings.test.tsx
@@ -337,7 +337,7 @@ describe('routes/Settings.tsx', () => {
     expect(ipcRenderer.send).toHaveBeenCalledWith('app-quit');
   });
 
-  it('should be able to enable colors', async () => {
+  it('should be able to enable detailed notifications', async () => {
     jest.spyOn(apiRequests, 'apiRequestAuth').mockResolvedValue({
       headers: {
         'x-oauth-scopes': Constants.AUTH_SCOPE.join(', '),
@@ -360,15 +360,15 @@ describe('routes/Settings.tsx', () => {
       );
     });
 
-    await screen.findByLabelText('Use GitHub-like state colors');
+    await screen.findByLabelText('Detailed notifications');
 
-    fireEvent.click(screen.getByLabelText('Use GitHub-like state colors'));
+    fireEvent.click(screen.getByLabelText('Detailed notifications'));
 
     expect(updateSetting).toHaveBeenCalledTimes(1);
-    expect(updateSetting).toHaveBeenCalledWith('colors', true);
+    expect(updateSetting).toHaveBeenCalledWith('detailedNotifications', true);
   });
 
-  it('should not be able to enable colors due to missing scope', async () => {
+  it('should not be able to enable detailed notifications due to missing scope', async () => {
     jest.spyOn(apiRequests, 'apiRequestAuth').mockResolvedValue({
       headers: {
         'x-oauth-scopes': 'read:user, notifications',
@@ -393,29 +393,24 @@ describe('routes/Settings.tsx', () => {
 
     expect(
       screen
-        .getByLabelText('Use GitHub-like state colors (requires repo scope)')
+        .getByLabelText('Detailed notifications (requires repo scope)')
         .closest('input'),
     ).toHaveProperty('disabled', true);
 
     // click the checkbox
     fireEvent.click(
-      screen.getByLabelText(
-        'Use GitHub-like state colors (requires repo scope)',
-      ),
+      screen.getByLabelText('Detailed notifications (requires repo scope)'),
     );
 
     // check if the checkbox is still unchecked
     expect(updateSetting).not.toHaveBeenCalled();
     expect(
-      screen.getByLabelText(
-        'Use GitHub-like state colors (requires repo scope)',
-      ),
+      screen.getByLabelText('Detailed notifications (requires repo scope)'),
     ).not.toBe('checked');
 
     expect(
-      screen.getByLabelText(
-        'Use GitHub-like state colors (requires repo scope)',
-      ).parentNode.parentNode,
+      screen.getByLabelText('Detailed notifications (requires repo scope)')
+        .parentNode.parentNode,
     ).toMatchSnapshot();
   });
 
diff --git a/src/routes/__snapshots__/LoginEnterprise.test.tsx.snap b/src/routes/__snapshots__/LoginEnterprise.test.tsx.snap
index 109d0a93..0efd39df 100644
--- a/src/routes/__snapshots__/LoginEnterprise.test.tsx.snap
+++ b/src/routes/__snapshots__/LoginEnterprise.test.tsx.snap
@@ -49,7 +49,7 @@ exports[`routes/LoginEnterprise.tsx renders correctly 1`] = `
       onSubmit={[Function]}
     >
       <div
-        className="mt-2"
+        className="mb-4"
       >
         <label
           className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
@@ -71,7 +71,7 @@ exports[`routes/LoginEnterprise.tsx renders correctly 1`] = `
         />
       </div>
       <div
-        className="mt-2"
+        className="mb-4"
       >
         <label
           className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
@@ -93,7 +93,7 @@ exports[`routes/LoginEnterprise.tsx renders correctly 1`] = `
         />
       </div>
       <div
-        className="mt-2"
+        className="mb-4"
       >
         <label
           className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
diff --git a/src/routes/__snapshots__/LoginWithToken.test.tsx.snap b/src/routes/__snapshots__/LoginWithToken.test.tsx.snap
index 36969118..58b6d25c 100644
--- a/src/routes/__snapshots__/LoginWithToken.test.tsx.snap
+++ b/src/routes/__snapshots__/LoginWithToken.test.tsx.snap
@@ -49,7 +49,7 @@ exports[`routes/LoginWithToken.tsx renders correctly 1`] = `
       onSubmit={[Function]}
     >
       <div
-        className="mt-2"
+        className="mb-4"
       >
         <label
           className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
@@ -74,24 +74,26 @@ exports[`routes/LoginWithToken.tsx renders correctly 1`] = `
         >
           <div>
             <div>
-              Create a Personal Access Token on GitHub and paste above.
-            </div>
-            <div>
-              The required scopes will be selected for you.
-               
               <button
-                className="px-2 py-1 my-2 text-xs rounded bg-gray-300 font-semibold rounded text-sm text-center hover:bg-gray-500 hover:text-white dark:text-black focus:outline-none cursor-pointer"
+                className="px-2 py-1 text-xs rounded bg-gray-300 font-semibold rounded text-sm text-center hover:bg-gray-500 hover:text-white dark:text-black focus:outline-none cursor-pointer"
                 onClick={[Function]}
                 type="button"
               >
                 Generate a PAT
               </button>
+               
+              on GitHub and paste above.
+            </div>
+            <div
+              className="italic mt-1"
+            >
+              The required scopes will be selected for you.
             </div>
           </div>
         </div>
       </div>
       <div
-        className="mt-2"
+        className="mb-4"
       >
         <label
           className="block tracking-wide text-grey-dark text-sm font-semibold mb-2"
@@ -119,7 +121,7 @@ exports[`routes/LoginWithToken.tsx renders correctly 1`] = `
               Defaults to github.com.
             </div>
             <div
-              className="italic"
+              className="italic mt-1"
             >
               Change only if you are using GitHub Enterprise Server.
             </div>
diff --git a/src/routes/__snapshots__/Settings.test.tsx.snap b/src/routes/__snapshots__/Settings.test.tsx.snap
index e9448a0e..61785791 100644
--- a/src/routes/__snapshots__/Settings.test.tsx.snap
+++ b/src/routes/__snapshots__/Settings.test.tsx.snap
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`routes/Settings.tsx should not be able to enable colors due to missing scope 1`] = `
+exports[`routes/Settings.tsx should not be able to enable detailed notifications due to missing scope 1`] = `
 <div
   class="flex items-start"
 >
@@ -10,7 +10,7 @@ exports[`routes/Settings.tsx should not be able to enable colors due to missing
     <input
       class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
       disabled=""
-      id="colors"
+      id="detailedNotifications"
       type="checkbox"
     />
   </div>
@@ -19,10 +19,10 @@ exports[`routes/Settings.tsx should not be able to enable colors due to missing
   >
     <label
       class="font-medium text-gray-700 dark:text-gray-200"
-      for="colors"
+      for="detailedNotifications"
       style="text-decoration: line-through;"
     >
-      Use GitHub-like state colors (requires repo scope)
+      Detailed notifications (requires repo scope)
     </label>
   </div>
 </div>
@@ -162,7 +162,7 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
           >
             <input
               class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
-              id="colors"
+              id="detailedNotifications"
               type="checkbox"
             />
           </div>
@@ -171,10 +171,10 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
           >
             <label
               class="font-medium text-gray-700 dark:text-gray-200"
-              for="colors"
+              for="detailedNotifications"
               style=""
             >
-              Use GitHub-like state colors
+              Detailed notifications
             </label>
           </div>
         </div>
@@ -334,11 +334,6 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
             </label>
           </div>
         </div>
-        <div
-          class="text-xs mt-1 italic text-gray-500 dark:text-gray-300"
-        >
-          Changes will take effect after restarting the app
-        </div>
       </div>
       <div
         class="mt-1 mb-3 text-sm"