diff --git a/src/components/settings/settings/EditSettingsForm.tsx b/src/components/settings/settings/EditSettingsForm.tsx index 2900aa2af6..3d75d7a59b 100644 --- a/src/components/settings/settings/EditSettingsForm.tsx +++ b/src/components/settings/settings/EditSettingsForm.tsx @@ -200,6 +200,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.', @@ -1172,6 +1176,28 @@ class EditSettingsForm extends Component { })}

+ +
+ +
+

{intl.formatMessage(messages.subheadlineShortcuts)}

+ + this.submit(e)} + {...form.$('shortcutActivateNextService').bind()} + /> + + this.submit(e)} + {...form.$('shortcutActivatePreviousService').bind()} + /> + +

+ {intl.formatMessage(messages.appRestartRequired)} +

+
)} diff --git a/src/config.ts b/src/config.ts index 0034b00a65..ec0519235a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,6 +2,8 @@ import ms from 'ms'; +import { cmdOrCtrlShortcutKey, 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'; @@ -469,3 +471,8 @@ export const DEFAULT_SERVICE_SETTINGS = { darkReaderContrast: 90, darkReaderSepia: 10, }; + +export const DEFAULT_SHORTCUTS = { + activateNextService: `${cmdOrCtrlShortcutKey()}+tab`, + activatePreviousService: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+tab`, +}; diff --git a/src/containers/settings/EditSettingsScreen.tsx b/src/containers/settings/EditSettingsScreen.tsx index 31e8d64840..d765955395 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'); @@ -499,6 +501,11 @@ class EditSettingsScreen extends Component< locale: settingsData.locale, // we need this info in the main process as well }; + const newShortcuts = { + activateNextService: settingsData.shortcutActivateNextService, + activatePreviousService: settingsData.shortcutActivatePreviousService, + }; + const requiredRestartKeys = [ 'webRTCIPHandlingPolicy', 'sentry', @@ -539,6 +546,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), @@ -1297,6 +1310,24 @@ class EditSettingsScreen extends Component< default: DEFAULT_APP_SETTINGS.automaticUpdates, 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 9ea73cf2a7..69067897d2 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -317,6 +317,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, }; }