Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(settings): keyboard shortcut to open app #1260

Merged
merged 9 commits into from
Jun 18, 2024
26 changes: 25 additions & 1 deletion main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
const { ipcMain: ipc, app, nativeTheme, Menu } = require('electron/main');
const {
ipcMain: ipc,
app,
nativeTheme,
globalShortcut,
Menu,
} = require('electron/main');
const { menubar } = require('menubar');
const { autoUpdater } = require('electron-updater');
const { onFirstRunMaybe } = require('./first-run');
Expand Down Expand Up @@ -122,6 +128,24 @@ app.whenReady().then(async () => {
}
});

ipc.on(
'gitify:update-keyboard-shortcut',
(_, { enabled, keyboardShortcut }) => {
if (!enabled) {
globalShortcut.unregister(keyboardShortcut);
return;
}

globalShortcut.register(keyboardShortcut, () => {
if (mb.window.isVisible()) {
mb.hideWindow();
} else {
mb.showWindow();
}
});
},
);

ipc.on('gitify:update-auto-launch', (_, settings) => {
app.setLoginItemSettings(settings);
});
Expand Down
1 change: 1 addition & 0 deletions src/__mocks__/state-mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export const mockSettings: SettingsState = {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
keyboardShortcut: true,
};

export const mockState: GitifyState = {
Expand Down
2 changes: 2 additions & 0 deletions src/context/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ describe('context/App.tsx', () => {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
keyboardShortcut: true,
} as SettingsState,
});
});
Expand Down Expand Up @@ -430,6 +431,7 @@ describe('context/App.tsx', () => {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
keyboardShortcut: true,
} as SettingsState,
});
});
Expand Down
12 changes: 11 additions & 1 deletion src/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import {
getUserData,
removeAccount,
} from '../utils/auth/utils';
import { setAutoLaunch, updateTrayTitle } from '../utils/comms';
import {
setAutoLaunch,
setKeyboardShortcut,
updateTrayTitle,
} from '../utils/comms';
import Constants from '../utils/constants';
import { getNotificationCount } from '../utils/notifications';
import { clearState, loadState, saveState } from '../utils/storage';
Expand All @@ -57,6 +61,7 @@ export const defaultSettings: SettingsState = {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
keyboardShortcut: true,
};

interface AppContextState {
Expand Down Expand Up @@ -140,6 +145,10 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
}
}, [settings.showNotificationsCountInTray, notifications]);

useEffect(() => {
setKeyboardShortcut(settings.keyboardShortcut);
}, [settings.keyboardShortcut]);

const updateSetting = useCallback(
(name: keyof SettingsState, value: boolean | Theme) => {
if (name === 'openAtStartup') {
Expand Down Expand Up @@ -220,6 +229,7 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
}

if (existing.settings) {
setKeyboardShortcut(existing.settings.keyboardShortcut);
setSettings({ ...defaultSettings, ...existing.settings });
return existing.settings;
}
Expand Down
25 changes: 25 additions & 0 deletions src/routes/Settings.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,31 @@ describe('routes/Settings.tsx', () => {
});

describe('System section', () => {
it('should toggle the keyboardShortcut checkbox', async () => {
await act(async () => {
render(
<AppContext.Provider
value={{
auth: mockAuth,
settings: mockSettings,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
</AppContext.Provider>,
);
});

fireEvent.click(screen.getByLabelText('Enable keyboard shortcut'), {
target: { checked: true },
});

expect(updateSetting).toHaveBeenCalledTimes(1);
expect(updateSetting).toHaveBeenCalledWith('keyboardShortcut', false);
});

it('should toggle the showNotificationsCountInTray checkbox', async () => {
await act(async () => {
render(
Expand Down
20 changes: 19 additions & 1 deletion src/routes/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { AppContext } from '../context/App';
import { BUTTON_CLASS_NAME } from '../styles/gitify';
import { Theme } from '../types';
import { getAppVersion, quitApp } from '../utils/comms';
import Constants from '../utils/constants';
import {
openGitHubParticipatingDocs,
openGitifyReleaseNotes,
Expand Down Expand Up @@ -211,7 +212,7 @@ export const SettingsRoute: FC = () => {
<div>
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)
window (scheduled or user initiated).
</div>
}
/>
Expand All @@ -221,6 +222,23 @@ export const SettingsRoute: FC = () => {
<legend id="system" className="mb-1 mt-2 font-semibold">
System
</legend>
<Checkbox
name="kbdShortcutEnabled"
label="Enable keyboard shortcut"
checked={!!settings.keyboardShortcut}
onChange={(evt) =>
updateSetting('keyboardShortcut', evt.target.checked)
}
tooltip={
<div>
When enabled you can choose to use the hotkeys{' '}
<span className="text-orange-600">
{Constants.DEFAULT_KEYBOARD_SHORTCUT}
</span>{' '}
to show or hide Gitify.
</div>
}
/>
{isMacOS() && (
<Checkbox
name="showNotificationsCountInTray"
Expand Down
48 changes: 48 additions & 0 deletions src/routes/__snapshots__/Settings.test.tsx.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ interface SystemSettingsState {
playSound: boolean;
openAtStartup: boolean;
showNotificationsCountInTray: boolean;
keyboardShortcut: boolean;
}

export interface GitifyState {
Expand Down
8 changes: 8 additions & 0 deletions src/utils/comms.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ipcRenderer, shell } from 'electron';
import type { Link } from '../types';
import Constants from './constants';

export function openExternalLink(url: Link): void {
if (!url.toLowerCase().startsWith('file:///')) {
Expand Down Expand Up @@ -30,6 +31,13 @@ export function setAutoLaunch(value: boolean): void {
});
}

export function setKeyboardShortcut(keyboardShortcut: boolean): void {
ipcRenderer.send('gitify:update-keyboard-shortcut', {
enabled: keyboardShortcut,
keyboardShortcut: Constants.DEFAULT_KEYBOARD_SHORTCUT,
});
}

export function updateTrayIcon(notificationsLength = 0): void {
if (notificationsLength > 0) {
ipcRenderer.send('gitify:icon-active');
Expand Down
2 changes: 2 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const Constants = {

FETCH_INTERVAL: 60000,

DEFAULT_KEYBOARD_SHORTCUT: 'CommandOrControl+Shift+G',

// GitHub Docs
GITHUB_DOCS: {
OAUTH_URL:
Expand Down