From 167a6a009a4acc16515c97425a7ef9bf4b28722e Mon Sep 17 00:00:00 2001
From: insidewhy <97685+insidewhy@users.noreply.github.com>
Date: Sat, 12 Oct 2024 17:48:47 +0800
Subject: [PATCH] Allow customising shortcuts for activating next/previous
service, see #53 (#1920)
Fixes https://github.com/ferdium/ferdium-app/issues/53
---
.../settings/settings/EditSettingsForm.tsx | 22 +++++++++++++
src/config.ts | 9 +++++-
.../settings/EditSettingsScreen.tsx | 31 +++++++++++++++++++
src/i18n/locales/en-US.json | 1 +
src/index.ts | 8 ++++-
src/lib/Menu.ts | 6 ++--
src/stores/SettingsStore.ts | 7 +++++
7 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/src/components/settings/settings/EditSettingsForm.tsx b/src/components/settings/settings/EditSettingsForm.tsx
index 0a8d115379..310fbfa5ec 100644
--- a/src/components/settings/settings/EditSettingsForm.tsx
+++ b/src/components/settings/settings/EditSettingsForm.tsx
@@ -201,6 +201,10 @@ const messages = defineMessages({
id: 'settings.app.subheadlineDownloads',
defaultMessage: 'Downloads',
},
+ subheadlineShortcuts: {
+ id: 'settings.app.subheadlineShortcuts',
+ defaultMessage: 'Shortcuts',
+ },
cacheInfo: {
id: 'settings.app.cacheInfo',
defaultMessage: 'Ferdium cache is currently using {size} of disk space.',
@@ -1214,6 +1218,24 @@ class EditSettingsForm extends Component {
})}
+
+
+
+
+
{intl.formatMessage(messages.subheadlineShortcuts)}
+
+ this.submit(e)}
+ {...form.$('shortcutActivateNextService').bind()}
+ />
+
+ this.submit(e)}
+ {...form.$('shortcutActivatePreviousService').bind()}
+ />
+
)}
diff --git a/src/config.ts b/src/config.ts
index 02ee1279bf..5c85d23439 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -2,6 +2,8 @@
import ms from 'ms';
+import { shiftKey } from './environment';
+
export const DEFAULT_ACCENT_COLOR = '#7367F0';
export const CHECK_INTERVAL = ms('1h'); // How often should we perform checks
@@ -326,7 +328,7 @@ export const FERDIUM_TRANSLATION = 'https://crowdin.com/project/ferdium-app';
export const FERDIUM_DEV_DOCS =
'https://github.com/ferdium/ferdium-recipes/blob/main/docs/integration.md';
-export const FILE_SYSTEM_SETTINGS_TYPES = ['app', 'proxy'];
+export const FILE_SYSTEM_SETTINGS_TYPES = ['app', 'proxy', 'shortcuts'];
export const LOCAL_SERVER = 'You are using Ferdium without a server';
export const SERVER_NOT_LOADED = 'Ferdium::SERVER_NOT_LOADED';
@@ -470,3 +472,8 @@ export const DEFAULT_SERVICE_SETTINGS = {
darkReaderContrast: 90,
darkReaderSepia: 10,
};
+
+export const DEFAULT_SHORTCUTS = {
+ activateNextService: 'Ctrl+tab',
+ activatePreviousService: `Ctrl+${shiftKey()}+tab`,
+};
diff --git a/src/containers/settings/EditSettingsScreen.tsx b/src/containers/settings/EditSettingsScreen.tsx
index 6bf14c05c6..58dd33c76e 100644
--- a/src/containers/settings/EditSettingsScreen.tsx
+++ b/src/containers/settings/EditSettingsScreen.tsx
@@ -11,6 +11,7 @@ import type { StoresProps } from '../../@types/ferdium-components.types';
import type { FormFields } from '../../@types/mobx-form.types';
import {
DEFAULT_APP_SETTINGS,
+ DEFAULT_SHORTCUTS,
GOOGLE_TRANSLATOR_LANGUAGES,
HIBERNATION_STRATEGIES,
ICON_SIZES,
@@ -42,6 +43,7 @@ import ErrorBoundary from '../../components/util/ErrorBoundary';
import { importExportURL } from '../../api/apiBase';
import globalMessages from '../../i18n/globalMessages';
import { ifUndefined } from '../../jsUtils';
+import { menuItems } from '../../lib/Menu';
const debug = require('../../preload-safe-debug')('Ferdium:EditSettingsScreen');
@@ -504,6 +506,11 @@ class EditSettingsScreen extends Component<
sandboxServices: Boolean(settingsData.sandboxServices),
};
+ const newShortcuts = {
+ activateNextService: settingsData.shortcutActivateNextService,
+ activatePreviousService: settingsData.shortcutActivatePreviousService,
+ };
+
const requiredRestartKeys = [
'webRTCIPHandlingPolicy',
'sentry',
@@ -544,6 +551,12 @@ class EditSettingsScreen extends Component<
data: newSettings,
});
+ settings.update({
+ type: 'shortcuts',
+ // TODO: The conversions might not be necessary once we convert to typescript
+ data: newShortcuts,
+ });
+
user.update({
userData: {
automaticUpdates: Boolean(settingsData.automaticUpdates),
@@ -1311,6 +1324,24 @@ class EditSettingsScreen extends Component<
default: DEFAULT_APP_SETTINGS.sandboxServices,
type: 'checkbox',
},
+ shortcutActivateNextService: {
+ label: intl.formatMessage(menuItems.activateNextService),
+ value: ifUndefined(
+ settings.all.shortcuts.activateNextService,
+ DEFAULT_SHORTCUTS.activateNextService,
+ ),
+ default: DEFAULT_SHORTCUTS.activateNextService,
+ placeholder: DEFAULT_SHORTCUTS.activateNextService,
+ },
+ shortcutActivatePreviousService: {
+ label: intl.formatMessage(menuItems.activatePreviousService),
+ value: ifUndefined(
+ settings.all.shortcuts.activatePreviousService,
+ DEFAULT_SHORTCUTS.activatePreviousService,
+ ),
+ default: DEFAULT_SHORTCUTS.activatePreviousService,
+ placeholder: DEFAULT_SHORTCUTS.activatePreviousService,
+ },
},
};
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index a6a7b153ad..efaf5751ef 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -321,6 +321,7 @@
"settings.app.subheadlineCache": "Cache",
"settings.app.subheadlineDownloads": "Downloads",
"settings.app.subheadlineFerdiumProfile": "Ferdium Profile",
+ "settings.app.subheadlineShortcuts": "Shortcuts",
"settings.app.subheadlineUserAgent": "User Agent",
"settings.app.todoServerInfo": "This server will be used for the \"Ferdium Todo\" feature.",
"settings.app.translationHelp": "Help us to translate Ferdium into your language.",
diff --git a/src/index.ts b/src/index.ts
index 286b305c28..72928e2bab 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -22,7 +22,11 @@ import enforceMacOSAppLocation from './enforce-macos-app-location';
initializeRemote();
-import { DEFAULT_APP_SETTINGS, DEFAULT_WINDOW_OPTIONS } from './config';
+import {
+ DEFAULT_APP_SETTINGS,
+ DEFAULT_SHORTCUTS,
+ DEFAULT_WINDOW_OPTIONS,
+} from './config';
import { altKey, isLinux, isMac, isWindows } from './environment';
import {
@@ -95,6 +99,7 @@ if (isWindows) {
// Initialize Settings
const settings = new Settings('app', DEFAULT_APP_SETTINGS);
const proxySettings = new Settings('proxy');
+const shortcutSettings = new Settings('shortcuts', DEFAULT_SHORTCUTS);
const retrieveSettingValue = (key: string, defaultValue: boolean | string) =>
ifUndefined(settings.get(key), defaultValue);
@@ -283,6 +288,7 @@ const createWindow = () => {
settings: {
app: settings,
proxy: proxySettings,
+ shortcuts: shortcutSettings,
},
trayIcon,
});
diff --git a/src/lib/Menu.ts b/src/lib/Menu.ts
index 05a456ac50..01ecf4320f 100644
--- a/src/lib/Menu.ts
+++ b/src/lib/Menu.ts
@@ -51,7 +51,7 @@ import { acceleratorString } from '../jsUtils';
import type Service from '../models/Service';
import type { RealStores } from '../stores';
-const menuItems = defineMessages({
+export const menuItems = defineMessages({
edit: {
id: 'menu.edit',
defaultMessage: 'Edit',
@@ -1102,7 +1102,7 @@ class FranzMenu implements StoresProps {
},
{
label: intl.formatMessage(menuItems.activateNextService),
- accelerator: `${cmdOrCtrlShortcutKey()}+tab`,
+ accelerator: this.stores.settings.shortcuts.activateNextService,
click: () => this.actions.service.setActiveNext(),
visible: !cmdAltShortcutsVisibile,
},
@@ -1114,7 +1114,7 @@ class FranzMenu implements StoresProps {
},
{
label: intl.formatMessage(menuItems.activatePreviousService),
- accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+tab`,
+ accelerator: this.stores.settings.shortcuts.activatePreviousService,
click: () => this.actions.service.setActivePrev(),
visible: !cmdAltShortcutsVisibile,
},
diff --git a/src/stores/SettingsStore.ts b/src/stores/SettingsStore.ts
index 29f173f910..7e92dd8cff 100644
--- a/src/stores/SettingsStore.ts
+++ b/src/stores/SettingsStore.ts
@@ -7,6 +7,7 @@ import type { Actions } from '../actions/lib/actions';
import type { ApiInterface } from '../api';
import {
DEFAULT_APP_SETTINGS,
+ DEFAULT_SHORTCUTS,
FILE_SYSTEM_SETTINGS_TYPES,
LOCAL_SERVER,
} from '../config';
@@ -23,6 +24,7 @@ export default class SettingsStore extends TypedStore {
@observable _fileSystemSettingsCache = {
app: DEFAULT_APP_SETTINGS,
proxy: {},
+ shortcuts: DEFAULT_SHORTCUTS,
};
constructor(stores: Stores, api: ApiInterface, actions: Actions) {
@@ -126,6 +128,10 @@ export default class SettingsStore extends TypedStore {
);
}
+ @computed get shortcuts() {
+ return this._fileSystemSettingsCache.shortcuts || DEFAULT_SHORTCUTS;
+ }
+
@computed get stats() {
return (
localStorage.getItem('stats') || {
@@ -145,6 +151,7 @@ export default class SettingsStore extends TypedStore {
service: this.service,
stats: this.stats,
migration: this.migration,
+ shortcuts: this.shortcuts,
};
}