mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-11 18:24:43 +02:00
Merge branch 'dev' of https://github.com/laurent22/joplin into dev
This commit is contained in:
commit
ed2ccdd504
@ -126,6 +126,7 @@ ElectronClient/gui/MainScreen/commands/toggleSideBar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/menuCommandNames.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -120,6 +120,7 @@ ElectronClient/gui/MainScreen/commands/toggleSideBar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/menuCommandNames.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
|
1
.ignore
1
.ignore
@ -69,6 +69,7 @@ ElectronClient/gui/MainScreen/commands/toggleSideBar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/menuCommandNames.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
|
@ -45,10 +45,12 @@ class Command extends BaseCommand {
|
||||
|
||||
const startDecryption = async () => {
|
||||
this.stdout(_('Starting decryption... Please wait as it may take several minutes depending on how much there is to decrypt.'));
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const result = await DecryptionWorker.instance().start();
|
||||
|
||||
if (result.error) throw result.error;
|
||||
|
||||
const line = [];
|
||||
line.push(_('Decrypted items: %d', result.decryptedItemCount));
|
||||
if (result.skippedItemCount) line.push(_('Skipped items: %d (use --retry-failed-items to retry decrypting them)', result.skippedItemCount));
|
||||
|
@ -13,8 +13,10 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
"X-Generator: Poedit 2.4.1\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
#: CliClient/app/command-cp.js:13
|
||||
msgid ""
|
||||
@ -315,8 +317,9 @@ msgid "Sync to provided target (defaults to sync.target config value)"
|
||||
msgstr "Synchroniseren naar opgegeven doel (standaard is dit sync.target)"
|
||||
|
||||
#: CliClient/app/command-sync.js:35
|
||||
#, fuzzy
|
||||
msgid "Upgrade the sync target to the latest version."
|
||||
msgstr ""
|
||||
msgstr "Sync target updaten naar de nieuwste versie."
|
||||
|
||||
#: CliClient/app/command-sync.js:81 CliClient/app/command-sync.js:95
|
||||
#: ElectronClient/gui/OneDriveLoginScreen.min.js:40
|
||||
@ -818,6 +821,8 @@ msgstr "Annuleren"
|
||||
msgid ""
|
||||
"The app is now going to close. Please relaunch it to complete the process."
|
||||
msgstr ""
|
||||
"De applicatie zal nu afsluiten. Gelieve het weer op te starten om het proces "
|
||||
"te voltooien."
|
||||
|
||||
#: ElectronClient/plugins/GotoAnything.min.js:459
|
||||
msgid ""
|
||||
@ -835,15 +840,14 @@ msgid "Goto Anything..."
|
||||
msgstr "Ga naar Alles..."
|
||||
|
||||
#: ElectronClient/plugins/GotoAnything.js:431
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Type a note title or part of its content to jump to it. Or type # followed "
|
||||
"by a tag name, or @ followed by a notebook name. Or type : to search for "
|
||||
"commands."
|
||||
msgstr ""
|
||||
"Typ de titel van een notitie of een deel van de inhoud om er naartoe te "
|
||||
"springen. Of typ # gevolgd door de naam van een label, of @ gevolgd door de "
|
||||
"naam van een notitieboek."
|
||||
"springen. Typ # gevolgd door de naam van een label, @ gevolgd door de naam "
|
||||
"van een notitieboek, of : om te zoeken op commando's."
|
||||
|
||||
#: ElectronClient/plugins/GotoAnything.js:463
|
||||
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:28
|
||||
@ -884,9 +888,8 @@ msgid "New version: %s"
|
||||
msgstr "Nieuwe versie: %s"
|
||||
|
||||
#: ElectronClient/checkForUpdates.js:154
|
||||
#, fuzzy
|
||||
msgid "Download"
|
||||
msgstr "Gedownload"
|
||||
msgstr "Downloaden"
|
||||
|
||||
#: ElectronClient/checkForUpdates.js:154
|
||||
msgid "Full Release Notes"
|
||||
@ -1235,13 +1238,15 @@ msgstr "Bezig met creëren van nieuw(e) %s..."
|
||||
|
||||
#: ElectronClient/gui/NoteEditor/NoteEditor.js:379
|
||||
msgid "The following attachments are being watched for changes:"
|
||||
msgstr ""
|
||||
msgstr "De volgende bijlagen worden gecontroleerd op wijzigingen:"
|
||||
|
||||
#: ElectronClient/gui/NoteEditor/NoteEditor.js:382
|
||||
msgid ""
|
||||
"The attachments will no longer be watched when you switch to a different "
|
||||
"note."
|
||||
msgstr ""
|
||||
"De bijlagen worden niet meer gecontroleerd wanneer je naar een andere "
|
||||
"notitie schakelt."
|
||||
|
||||
#: ElectronClient/gui/NoteEditor/NoteEditor.js:387
|
||||
#: ElectronClient/gui/NoteText.min.js:1656
|
||||
@ -1358,9 +1363,9 @@ msgstr "Eigenschappen van notitie"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:63
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:144
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Error: %s"
|
||||
msgstr "Fout"
|
||||
msgstr "Fout: %s"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:121
|
||||
#: ElectronClient/gui/Root.min.js:91 ElectronClient/gui/MenuBar.js:391
|
||||
@ -1370,12 +1375,11 @@ msgstr "Importeren"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:126
|
||||
msgid "Command"
|
||||
msgstr ""
|
||||
msgstr "Commando"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:127
|
||||
#, fuzzy
|
||||
msgid "Keyboard Shortcut"
|
||||
msgstr "Toetsenbordmodus"
|
||||
msgstr "Sneltoets"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:14
|
||||
#: ElectronClient/gui/MenuBar.js:178 ElectronClient/app.js:347
|
||||
@ -1398,9 +1402,8 @@ msgid "Website and documentation"
|
||||
msgstr "Website en documentatie"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:24
|
||||
#, fuzzy
|
||||
msgid "Hide Joplin"
|
||||
msgstr "Over Joplin"
|
||||
msgstr "Joplin verbergen"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:26
|
||||
#: ElectronClient/gui/MenuBar.js:428
|
||||
@ -1408,9 +1411,8 @@ msgid "Close Window"
|
||||
msgstr "Venster afsluiten"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:30
|
||||
#, fuzzy
|
||||
msgid "Preferences"
|
||||
msgstr "Voorkeuren..."
|
||||
msgstr "Voorkeuren"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:30
|
||||
#: ElectronClient/gui/Root.min.js:92 ElectronClient/gui/MenuBar.js:304
|
||||
@ -1420,13 +1422,15 @@ msgstr "Opties"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:49
|
||||
msgid "Press the shortcut"
|
||||
msgstr ""
|
||||
msgstr "Druk op de sneltoetsen"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:49
|
||||
msgid ""
|
||||
"Press the shortcut and then press ENTER. Or, press BACKSPACE to clear the "
|
||||
"shortcut."
|
||||
msgstr ""
|
||||
"Druk op de sneltoetsen en dan op ENTER. Of, druk op backspace om de "
|
||||
"sneltoets te wissen."
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:50
|
||||
#: ElectronClient/gui/EncryptionConfigScreen.min.js:96
|
||||
@ -1436,17 +1440,20 @@ msgstr "Opslaan"
|
||||
|
||||
#: ElectronClient/gui/MainScreen/MainScreen.js:418
|
||||
#: ElectronClient/gui/MainScreen/MainScreen.min.js:301
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"The sync target needs to be upgraded before Joplin can sync. The operation "
|
||||
"may take a few minutes to complete and the app needs to be restarted. To "
|
||||
"proceed please click on the link."
|
||||
msgstr ""
|
||||
"De sync target moet worden geüpdatet voordat Joplin kan synchroniseren. Het "
|
||||
"kan een paar minuten duren en de app moet opnieuw opgestart worden. Om door "
|
||||
"te gaan, klik op de link."
|
||||
|
||||
#: ElectronClient/gui/MainScreen/MainScreen.js:420
|
||||
#: ElectronClient/gui/MainScreen/MainScreen.min.js:306
|
||||
#, fuzzy
|
||||
msgid "Restart and upgrade"
|
||||
msgstr "Hoofdsleutels die moeten worden bijgewerkt"
|
||||
msgstr "Opnieuw opstarten en bijwerken"
|
||||
|
||||
#: ElectronClient/gui/MainScreen/MainScreen.js:424
|
||||
#: ElectronClient/gui/MainScreen/MainScreen.min.js:313
|
||||
@ -2268,18 +2275,16 @@ msgstr[0] "Kopieer Deelbare Link"
|
||||
msgstr[1] "Kopieer Deelbare Links"
|
||||
|
||||
#: ElectronClient/commands/toggleExternalEditing.js:18
|
||||
#, fuzzy
|
||||
msgid "Toggle external editing"
|
||||
msgstr "Klik om extern bewerken te stoppen"
|
||||
msgstr "Extern bewerken in- of uitschakelen"
|
||||
|
||||
#: ElectronClient/commands/toggleExternalEditing.js:37
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
msgstr "Stop"
|
||||
|
||||
#: ElectronClient/commands/copyDevCommand.js:18
|
||||
#, fuzzy
|
||||
msgid "Copy dev mode command to clipboard"
|
||||
msgstr "Pad kopiëren naar klembord"
|
||||
msgstr "Ontwikkelaarsmodus commando kopiëren naar klembord"
|
||||
|
||||
#: ElectronClient/commands/stopExternalEditing.js:18
|
||||
msgid "Stop external editing"
|
||||
@ -2291,9 +2296,8 @@ msgid "Error opening note in editor: %s"
|
||||
msgstr "Fout bij openen van notitie in editor: %s"
|
||||
|
||||
#: ElectronClient/commands/openProfileDirectory.js:18
|
||||
#, fuzzy
|
||||
msgid "Open profile directory"
|
||||
msgstr "Open sjabloon map"
|
||||
msgstr "Open profiel map"
|
||||
|
||||
#: ElectronClient/app.js:345
|
||||
#, javascript-format
|
||||
@ -2339,7 +2343,7 @@ msgstr ""
|
||||
|
||||
#: ReactNativeClient/lib/SyncTargetAmazonS3.js:28
|
||||
msgid "AWS S3"
|
||||
msgstr ""
|
||||
msgstr "AWS S3"
|
||||
|
||||
#: ReactNativeClient/lib/SyncTargetDropbox.js:25
|
||||
msgid "Dropbox"
|
||||
@ -2483,19 +2487,19 @@ msgstr "WebDAV-wachtwoord"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:215
|
||||
msgid "AWS S3 bucket"
|
||||
msgstr ""
|
||||
msgstr "AWS S3 bucket"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:226
|
||||
msgid "AWS S3 URL"
|
||||
msgstr ""
|
||||
msgstr "AWS S3 URL"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:237
|
||||
msgid "AWS key"
|
||||
msgstr ""
|
||||
msgstr "AWS key"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:247
|
||||
msgid "AWS secret"
|
||||
msgstr ""
|
||||
msgstr "AWS secret"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:259
|
||||
msgid "Attachment download behaviour"
|
||||
@ -2955,9 +2959,8 @@ msgid "Web Clipper"
|
||||
msgstr "Webclipper"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:1310
|
||||
#, fuzzy
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Toetsenbordmodus"
|
||||
msgstr "Sneltoetsen"
|
||||
|
||||
#: ReactNativeClient/lib/models/Setting.js:1317
|
||||
msgid ""
|
||||
@ -3074,9 +3077,8 @@ msgid "Save alarm"
|
||||
msgstr "Alarm opslaan"
|
||||
|
||||
#: ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js:28
|
||||
#, fuzzy
|
||||
msgid "Open"
|
||||
msgstr "Openen..."
|
||||
msgstr "Openen"
|
||||
|
||||
#: ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js:29
|
||||
#: ReactNativeClient/lib/components/screens/Note.js:794
|
||||
@ -3114,8 +3116,9 @@ msgstr ""
|
||||
"Sommige items kunnen niet worden gesynchroniseerd. Klik voor meer informatie."
|
||||
|
||||
#: ReactNativeClient/lib/components/screen-header.js:453
|
||||
#, fuzzy
|
||||
msgid "The sync target needs to be upgraded. Press this banner to proceed."
|
||||
msgstr ""
|
||||
msgstr "De sync target moet worden geüpdatet. Druk hier om door te gaan."
|
||||
|
||||
#: ReactNativeClient/lib/components/side-menu-content.js:126
|
||||
#, javascript-format
|
||||
@ -3239,8 +3242,9 @@ msgid "Refresh"
|
||||
msgstr "Verversen"
|
||||
|
||||
#: ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js:42
|
||||
#, fuzzy
|
||||
msgid "Sync Target Upgrade"
|
||||
msgstr ""
|
||||
msgstr "Sync target update"
|
||||
|
||||
#: ReactNativeClient/lib/components/screens/NoteTagsDialog.js:163
|
||||
msgid "New tags:"
|
||||
@ -3484,11 +3488,14 @@ msgid ""
|
||||
"\n"
|
||||
"You may turn off this option at any time in the Configuration screen."
|
||||
msgstr ""
|
||||
"Om een geolocatie aan de notitie te koppelen, heeft de app uw toestemming "
|
||||
"nodig om toegang te krijgen tot uw locatie.\n"
|
||||
"\n"
|
||||
"U kunt deze optie op elk moment uitschakelen in het 'Configuratie'-scherm."
|
||||
|
||||
#: ReactNativeClient/lib/components/screens/Note.js:341
|
||||
#, fuzzy
|
||||
msgid "Permission needed"
|
||||
msgstr "Toestemming om de camera te gebruiken"
|
||||
msgstr "Toestemming vereist"
|
||||
|
||||
#: ReactNativeClient/lib/components/screens/Note.js:583
|
||||
#, javascript-format
|
||||
@ -3737,23 +3744,23 @@ msgstr "Geef een importformaat op voor %s"
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:240
|
||||
msgid "command"
|
||||
msgstr ""
|
||||
msgstr "commando"
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:240
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:245
|
||||
#, javascript-format
|
||||
msgid "\"%s\" is missing the required \"%s\" property."
|
||||
msgstr ""
|
||||
msgstr "\"%s\" mist de vereiste \"%s\" eigenschap."
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:245
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:252
|
||||
msgid "accelerator"
|
||||
msgstr ""
|
||||
msgstr "versneller"
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:252
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Invalid %s: %s."
|
||||
msgstr "Ongeldig antwoord: %s"
|
||||
msgstr "Ongeldig %s: %s."
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:270
|
||||
#, javascript-format
|
||||
@ -3761,11 +3768,13 @@ msgid ""
|
||||
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to "
|
||||
"unexpected behaviour."
|
||||
msgstr ""
|
||||
"Versneller \"%s\" wordt gebruikt voor \"%s\" en \"%s\" commando's. Dit kan "
|
||||
"tot onverwacht gedrag leiden."
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:295
|
||||
#, javascript-format
|
||||
msgid "Accelerator \"%s\" is not valid."
|
||||
msgstr ""
|
||||
msgstr "Versneller \"%s\" is niet geldig."
|
||||
|
||||
#: ReactNativeClient/lib/services/report.js:121
|
||||
msgid "Items that cannot be synchronised"
|
||||
|
@ -3,6 +3,7 @@ require('app-module-path').addPath(__dirname);
|
||||
const { tempFilePath } = require('test-utils.js');
|
||||
const KeymapService = require('lib/services/KeymapService').default;
|
||||
const keymapService = KeymapService.instance();
|
||||
keymapService.initialize([]);
|
||||
|
||||
describe('services_KeymapService', () => {
|
||||
describe('validateAccelerator', () => {
|
||||
@ -31,7 +32,7 @@ describe('services_KeymapService', () => {
|
||||
};
|
||||
|
||||
Object.entries(testCases).forEach(([platform, accelerators]) => {
|
||||
keymapService.initialize(platform);
|
||||
keymapService.initialize([], platform);
|
||||
accelerators.forEach(accelerator => {
|
||||
expect(() => keymapService.validateAccelerator(accelerator)).not.toThrow();
|
||||
});
|
||||
@ -69,7 +70,7 @@ describe('services_KeymapService', () => {
|
||||
};
|
||||
|
||||
Object.entries(testCases).forEach(([platform, accelerators]) => {
|
||||
keymapService.initialize(platform);
|
||||
keymapService.initialize([], platform);
|
||||
accelerators.forEach(accelerator => {
|
||||
expect(() => keymapService.validateAccelerator(accelerator)).toThrow();
|
||||
});
|
||||
@ -81,12 +82,12 @@ describe('services_KeymapService', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
|
||||
it('should allow registering new commands', async () => {
|
||||
keymapService.initialize('linux');
|
||||
keymapService.initialize([], 'linux');
|
||||
keymapService.registerCommandAccelerator('myCustomCommand', 'Ctrl+Shift+Alt+B');
|
||||
expect(keymapService.getAccelerator('myCustomCommand')).toEqual('Ctrl+Shift+Alt+B');
|
||||
|
||||
// Check that macOS key conversion is working
|
||||
keymapService.initialize('darwin');
|
||||
keymapService.initialize([], 'darwin');
|
||||
keymapService.registerCommandAccelerator('myCustomCommand', 'CmdOrCtrl+Shift+Alt+B');
|
||||
expect(keymapService.getAccelerator('myCustomCommand')).toEqual('Cmd+Shift+Option+B');
|
||||
keymapService.setAccelerator('myCustomCommand', 'Cmd+Shift+Option+X');
|
||||
@ -95,7 +96,7 @@ describe('services_KeymapService', () => {
|
||||
const keymapFilePath = tempFilePath('json');
|
||||
await keymapService.saveCustomKeymap(keymapFilePath);
|
||||
|
||||
keymapService.initialize('darwin');
|
||||
keymapService.initialize([], 'darwin');
|
||||
await keymapService.loadCustomKeymap(keymapFilePath);
|
||||
|
||||
expect(keymapService.getAccelerator('myCustomCommand')).toEqual('Cmd+Shift+Option+X');
|
||||
@ -106,17 +107,17 @@ describe('services_KeymapService', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
|
||||
it('should return the platform-specific default Accelerator', () => {
|
||||
keymapService.initialize('darwin');
|
||||
keymapService.initialize([], 'darwin');
|
||||
expect(keymapService.getAccelerator('newNote')).toEqual('Cmd+N');
|
||||
expect(keymapService.getAccelerator('synchronize')).toEqual('Cmd+S');
|
||||
expect(keymapService.getAccelerator('textSelectAll')).toEqual('Cmd+A');
|
||||
expect(keymapService.getAccelerator('textBold')).toEqual('Cmd+B');
|
||||
|
||||
keymapService.initialize('linux');
|
||||
keymapService.initialize([], 'linux');
|
||||
expect(keymapService.getAccelerator('newNote')).toEqual('Ctrl+N');
|
||||
expect(keymapService.getAccelerator('synchronize')).toEqual('Ctrl+S');
|
||||
|
||||
keymapService.initialize('win32');
|
||||
keymapService.initialize([], 'win32');
|
||||
expect(keymapService.getAccelerator('textSelectAll')).toEqual('Ctrl+A');
|
||||
expect(keymapService.getAccelerator('textBold')).toEqual('Ctrl+B');
|
||||
});
|
||||
@ -130,7 +131,7 @@ describe('services_KeymapService', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
|
||||
it('should update the Accelerator', () => {
|
||||
keymapService.initialize('darwin');
|
||||
keymapService.initialize(['print'], 'darwin');
|
||||
const testCases_Darwin = [
|
||||
{ command: 'newNote', accelerator: 'Ctrl+Option+Shift+N' },
|
||||
{ command: 'synchronize', accelerator: 'F11' },
|
||||
@ -147,7 +148,7 @@ describe('services_KeymapService', () => {
|
||||
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
|
||||
});
|
||||
|
||||
keymapService.initialize('linux');
|
||||
keymapService.initialize(['print'], 'linux');
|
||||
const testCases_Linux = [
|
||||
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
|
||||
{ command: 'synchronize', accelerator: 'F15' },
|
||||
@ -167,7 +168,7 @@ describe('services_KeymapService', () => {
|
||||
});
|
||||
|
||||
describe('getDefaultAccelerator', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
beforeEach(() => keymapService.initialize(['print', 'linux']));
|
||||
|
||||
it('should return the default accelerator', () => {
|
||||
const testCases = [
|
||||
@ -196,7 +197,7 @@ describe('services_KeymapService', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
|
||||
it('should update the keymap', () => {
|
||||
keymapService.initialize('darwin');
|
||||
keymapService.initialize([], 'darwin');
|
||||
const customKeymapItems_Darwin = [
|
||||
{ command: 'newNote', accelerator: 'Option+Shift+Cmd+N' },
|
||||
{ command: 'synchronize', accelerator: 'Ctrl+F11' },
|
||||
@ -217,7 +218,7 @@ describe('services_KeymapService', () => {
|
||||
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
|
||||
});
|
||||
|
||||
keymapService.initialize('win32');
|
||||
keymapService.initialize([], 'win32');
|
||||
const customKeymapItems_Win32 = [
|
||||
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
|
||||
{ command: 'synchronize', accelerator: 'Ctrl+F11' },
|
||||
|
@ -14,6 +14,7 @@ import Setting from 'lib/models/Setting';
|
||||
import actionApi from 'lib/services/rest/actionApi.desktop';
|
||||
import BaseApplication from 'lib/BaseApplication';
|
||||
import { _, setLocale } from 'lib/locale';
|
||||
import menuCommandNames from './gui/menuCommandNames';
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
@ -495,14 +496,6 @@ class Application extends BaseApplication {
|
||||
const filename = Setting.custom_css_files.JOPLIN_APP;
|
||||
await CssUtils.injectCustomStyles(`${dir}/${filename}`);
|
||||
|
||||
const keymapService = KeymapService.instance();
|
||||
|
||||
try {
|
||||
await keymapService.loadCustomKeymap(`${dir}/keymap-desktop.json`);
|
||||
} catch (err) {
|
||||
reg.logger().error(err.message);
|
||||
}
|
||||
|
||||
AlarmService.setDriver(new AlarmServiceDriverNode({ appName: packageInfo.build.appId }));
|
||||
AlarmService.setLogger(reg.logger());
|
||||
|
||||
@ -533,9 +526,21 @@ class Application extends BaseApplication {
|
||||
CommandService.instance().registerDeclaration(declaration);
|
||||
}
|
||||
|
||||
// Since the settings need to be loaded before the store is created, it will never
|
||||
// receive the SETTING_UPDATE_ALL even, which mean state.settings will not be
|
||||
// initialised. So we manually call dispatchUpdateAll() to force an update.
|
||||
const keymapService = KeymapService.instance();
|
||||
// We only add the commands that appear in the menu because only
|
||||
// those can have a shortcut associated with them.
|
||||
keymapService.initialize(menuCommandNames());
|
||||
|
||||
try {
|
||||
await keymapService.loadCustomKeymap(`${dir}/keymap-desktop.json`);
|
||||
} catch (error) {
|
||||
reg.logger().error(error);
|
||||
}
|
||||
|
||||
// Since the settings need to be loaded before the store is
|
||||
// created, it will never receive the SETTING_UPDATE_ALL even,
|
||||
// which mean state.settings will not be initialised. So we
|
||||
// manually call dispatchUpdateAll() to force an update.
|
||||
Setting.dispatchUpdateAll();
|
||||
|
||||
await FoldersScreenUtils.refreshFolders();
|
||||
|
@ -5,7 +5,7 @@ import { _ } from 'lib/locale';
|
||||
|
||||
const commandService = CommandService.instance();
|
||||
|
||||
const getLabel = (commandName: string) => {
|
||||
const getLabel = (commandName: string):string => {
|
||||
if (commandService.exists(commandName)) return commandService.label(commandName, true);
|
||||
|
||||
// Some commands are not registered in CommandService at the moment
|
||||
|
@ -1,11 +1,22 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import KeymapService, { KeymapItem } from 'lib/services/KeymapService';
|
||||
import getLabel from './getLabel';
|
||||
|
||||
const keymapService = KeymapService.instance();
|
||||
|
||||
// This custom hook provides a synchronized snapshot of the keymap residing at KeymapService
|
||||
// All the logic regarding altering and interacting with the keymap is isolated from the components
|
||||
|
||||
function allKeymapItems() {
|
||||
const output = keymapService.getKeymapItems().slice();
|
||||
|
||||
output.sort((a:KeymapItem, b:KeymapItem) => {
|
||||
return getLabel(a.command).toLocaleLowerCase() < getLabel(b.command).toLocaleLowerCase() ? -1 : +1;
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
const useKeymap = (): [
|
||||
KeymapItem[],
|
||||
Error,
|
||||
@ -13,7 +24,7 @@ const useKeymap = (): [
|
||||
(commandName: string, accelerator: string) => void,
|
||||
(commandName: string) => void
|
||||
] => {
|
||||
const [keymapItems, setKeymapItems] = useState<KeymapItem[]>(() => keymapService.getKeymapItems());
|
||||
const [keymapItems, setKeymapItems] = useState<KeymapItem[]>(() => allKeymapItems());
|
||||
const [keymapError, setKeymapError] = useState<Error>(null);
|
||||
const [mustSave, setMustSave] = useState(false);
|
||||
|
||||
@ -42,7 +53,7 @@ const useKeymap = (): [
|
||||
|
||||
const overrideKeymapItems = (customKeymapItems: KeymapItem[]) => {
|
||||
const oldKeymapItems = [...customKeymapItems];
|
||||
keymapService.initialize(); // Start with a fresh keymap
|
||||
keymapService.resetKeymap(); // Start with a fresh keymap
|
||||
|
||||
try {
|
||||
// First, try to update the in-memory keymap of KeymapService
|
||||
|
@ -14,6 +14,7 @@ import InteropServiceHelper from '../InteropServiceHelper';
|
||||
import { _ } from 'lib/locale';
|
||||
import { MenuItem, MenuItemLocation } from 'lib/services/plugins/api/types';
|
||||
import stateToWhenClauseContext from 'lib/services/commands/stateToWhenClauseContext';
|
||||
import menuCommandNames from './menuCommandNames';
|
||||
|
||||
const { connect } = require('react-redux');
|
||||
const { reg } = require('lib/registry.js');
|
||||
@ -86,39 +87,7 @@ interface Props {
|
||||
pluginMenus: any[],
|
||||
}
|
||||
|
||||
const commandNames:string[] = [
|
||||
'focusElementSideBar',
|
||||
'focusElementNoteList',
|
||||
'focusElementNoteTitle',
|
||||
'focusElementNoteBody',
|
||||
'exportPdf',
|
||||
'newNote',
|
||||
'newTodo',
|
||||
'newFolder',
|
||||
'newSubFolder',
|
||||
'print',
|
||||
'synchronize',
|
||||
'textCopy',
|
||||
'textCut',
|
||||
'textPaste',
|
||||
'textSelectAll',
|
||||
'textBold',
|
||||
'textItalic',
|
||||
'textLink',
|
||||
'textCode',
|
||||
'insertDateTime',
|
||||
'attachFile',
|
||||
'focusSearch',
|
||||
'showLocalSearch',
|
||||
'toggleSideBar',
|
||||
'toggleNoteList',
|
||||
'toggleVisiblePanes',
|
||||
'toggleExternalEditing',
|
||||
'setTags',
|
||||
'showNoteContentProperties',
|
||||
'copyDevCommand',
|
||||
'openProfileDirectory',
|
||||
];
|
||||
const commandNames:string[] = menuCommandNames();
|
||||
|
||||
function menuItemSetChecked(id:string, checked:boolean) {
|
||||
const menu = Menu.getApplicationMenu();
|
||||
@ -249,10 +218,8 @@ function useMenu(props:Props) {
|
||||
menuItemDic.focusElementNoteBody,
|
||||
];
|
||||
|
||||
let toolsItems:any[] = [];
|
||||
const importItems = [];
|
||||
const exportItems = [];
|
||||
const toolsItemsFirst = [];
|
||||
const templateItems:any[] = [];
|
||||
const ioService = InteropService.instance();
|
||||
const ioModules = ioService.modules();
|
||||
@ -299,16 +266,18 @@ function useMenu(props:Props) {
|
||||
},
|
||||
};
|
||||
|
||||
const separator = () => {
|
||||
return {
|
||||
type: 'separator',
|
||||
};
|
||||
};
|
||||
|
||||
const newNoteItem = menuItemDic.newNote;
|
||||
const newTodoItem = menuItemDic.newTodo;
|
||||
const newFolderItem = menuItemDic.newFolder;
|
||||
const newSubFolderItem = menuItemDic.newSubFolder;
|
||||
const printItem = menuItemDic.print;
|
||||
|
||||
toolsItemsFirst.push(syncStatusItem, {
|
||||
type: 'separator',
|
||||
});
|
||||
|
||||
templateItems.push({
|
||||
label: _('Create note from template'),
|
||||
click: () => {
|
||||
@ -342,18 +311,22 @@ function useMenu(props:Props) {
|
||||
},
|
||||
});
|
||||
|
||||
let toolsItems:any[] = [];
|
||||
|
||||
// we need this workaround, because on macOS the menu is different
|
||||
const toolsItemsWindowsLinux:any[] = toolsItemsFirst.concat([{
|
||||
label: _('Options'),
|
||||
visible: !shim.isMac(),
|
||||
accelerator: !shim.isMac() && keymapService.getAccelerator('config'),
|
||||
click: () => {
|
||||
props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Config',
|
||||
});
|
||||
const toolsItemsWindowsLinux:any[] = [
|
||||
{
|
||||
label: _('Options'),
|
||||
accelerator: keymapService.getAccelerator('config'),
|
||||
click: () => {
|
||||
props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Config',
|
||||
});
|
||||
},
|
||||
},
|
||||
} as any]);
|
||||
separator(),
|
||||
];
|
||||
|
||||
// the following menu items will be available for all OS under Tools
|
||||
const toolsItemsAll = [{
|
||||
@ -451,9 +424,7 @@ function useMenu(props:Props) {
|
||||
|
||||
menuItemDic.synchronize,
|
||||
|
||||
shim.isMac() ? syncStatusItem : noItem, {
|
||||
type: 'separator',
|
||||
}, shim.isMac() ? noItem : printItem, {
|
||||
shim.isMac() ? noItem : printItem, {
|
||||
type: 'separator',
|
||||
platforms: ['darwin'],
|
||||
},
|
||||
@ -518,12 +489,6 @@ function useMenu(props:Props) {
|
||||
});
|
||||
}
|
||||
|
||||
const separator = () => {
|
||||
return {
|
||||
type: 'separator',
|
||||
};
|
||||
};
|
||||
|
||||
const rootMenus:any = {
|
||||
edit: {
|
||||
id: 'edit',
|
||||
@ -586,11 +551,6 @@ function useMenu(props:Props) {
|
||||
},
|
||||
},
|
||||
separator(),
|
||||
{
|
||||
label: _('Focus'),
|
||||
submenu: focusItems,
|
||||
},
|
||||
separator(),
|
||||
{
|
||||
label: _('Actual Size'),
|
||||
click: () => {
|
||||
@ -623,6 +583,18 @@ function useMenu(props:Props) {
|
||||
accelerator: 'CommandOrControl+-',
|
||||
}],
|
||||
},
|
||||
go: {
|
||||
label: _('&Go'),
|
||||
submenu: [
|
||||
menuItemDic.historyBackward,
|
||||
menuItemDic.historyForward,
|
||||
separator(),
|
||||
{
|
||||
label: _('Focus'),
|
||||
submenu: focusItems,
|
||||
},
|
||||
],
|
||||
},
|
||||
note: {
|
||||
label: _('&Note'),
|
||||
submenu: [
|
||||
@ -655,6 +627,8 @@ function useMenu(props:Props) {
|
||||
click: () => _checkForUpdates(),
|
||||
},
|
||||
separator(),
|
||||
syncStatusItem,
|
||||
separator(),
|
||||
{
|
||||
id: 'help:toggleDevTools',
|
||||
label: _('Toggle development tools'),
|
||||
@ -709,6 +683,7 @@ function useMenu(props:Props) {
|
||||
const pluginMenuItems = PluginManager.instance().menuItems();
|
||||
for (const item of pluginMenuItems) {
|
||||
const itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools';
|
||||
itemParent.submenu.push(separator());
|
||||
itemParent.submenu.push(item);
|
||||
}
|
||||
}
|
||||
@ -741,6 +716,7 @@ function useMenu(props:Props) {
|
||||
rootMenus.file,
|
||||
rootMenus.edit,
|
||||
rootMenus.view,
|
||||
rootMenus.go,
|
||||
rootMenus.note,
|
||||
rootMenus.tools,
|
||||
rootMenus.help,
|
||||
@ -748,46 +724,6 @@ function useMenu(props:Props) {
|
||||
|
||||
if (shim.isMac()) template.splice(0, 0, rootMenus.macOsApp);
|
||||
|
||||
// TODO
|
||||
|
||||
// function isEmptyMenu(template:any[]) {
|
||||
// for (let i = 0; i < template.length; i++) {
|
||||
// const t = template[i];
|
||||
// if (t.type !== 'separator') return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// function removeUnwantedItems(template:any[], screen:string) {
|
||||
// const platform = shim.platformName();
|
||||
|
||||
// let output = [];
|
||||
// for (let i = 0; i < template.length; i++) {
|
||||
// const t = Object.assign({}, template[i]);
|
||||
// if (t.screens && t.screens.indexOf(screen) < 0) continue;
|
||||
// if (t.platforms && t.platforms.indexOf(platform) < 0) continue;
|
||||
// if (t.submenu) t.submenu = removeUnwantedItems(t.submenu, screen);
|
||||
// if (('submenu' in t) && isEmptyMenu(t.submenu)) continue;
|
||||
// output.push(t);
|
||||
// }
|
||||
|
||||
// // Remove empty separator for now empty sections
|
||||
// const temp = [];
|
||||
// let previous = null;
|
||||
// for (let i = 0; i < output.length; i++) {
|
||||
// const t = Object.assign({}, output[i]);
|
||||
// if (t.type === 'separator') {
|
||||
// if (!previous) continue;
|
||||
// if (previous.type === 'separator') continue;
|
||||
// }
|
||||
// temp.push(t);
|
||||
// previous = t;
|
||||
// }
|
||||
// output = temp;
|
||||
|
||||
// return output;
|
||||
// }
|
||||
|
||||
if (props.routeName !== 'Main') {
|
||||
setMenu(Menu.buildFromTemplate([
|
||||
{
|
||||
|
37
ElectronClient/gui/menuCommandNames.ts
Normal file
37
ElectronClient/gui/menuCommandNames.ts
Normal file
@ -0,0 +1,37 @@
|
||||
export default function() {
|
||||
return [
|
||||
'attachFile',
|
||||
'copyDevCommand',
|
||||
'exportPdf',
|
||||
'focusElementNoteBody',
|
||||
'focusElementNoteList',
|
||||
'focusElementNoteTitle',
|
||||
'focusElementSideBar',
|
||||
'focusSearch',
|
||||
'historyBackward',
|
||||
'historyForward',
|
||||
'insertDateTime',
|
||||
'newFolder',
|
||||
'newNote',
|
||||
'newSubFolder',
|
||||
'newTodo',
|
||||
'openProfileDirectory',
|
||||
'print',
|
||||
'setTags',
|
||||
'showLocalSearch',
|
||||
'showNoteContentProperties',
|
||||
'synchronize',
|
||||
'textBold',
|
||||
'textCode',
|
||||
'textCopy',
|
||||
'textCut',
|
||||
'textItalic',
|
||||
'textLink',
|
||||
'textPaste',
|
||||
'textSelectAll',
|
||||
'toggleExternalEditing',
|
||||
'toggleNoteList',
|
||||
'toggleSideBar',
|
||||
'toggleVisiblePanes',
|
||||
];
|
||||
}
|
2
ElectronClient/package-lock.json
generated
2
ElectronClient/package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.3.10",
|
||||
"version": "1.3.11",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.3.10",
|
||||
"version": "1.3.11",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
@ -557,7 +557,7 @@ GotoAnything.manifest = {
|
||||
menuItems: [
|
||||
{
|
||||
name: 'main',
|
||||
parent: 'tools',
|
||||
parent: 'go',
|
||||
label: _('Goto Anything...'),
|
||||
accelerator: () => KeymapService.instance().getAccelerator('gotoAnything'),
|
||||
screens: ['Main'],
|
||||
|
@ -211,7 +211,9 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
};
|
||||
|
||||
this.useBetaEditor = () => {
|
||||
return Setting.value('editor.beta') && Platform.OS !== 'android';
|
||||
// Disable for now
|
||||
return false;
|
||||
// return Setting.value('editor.beta') && Platform.OS !== 'android';
|
||||
};
|
||||
|
||||
this.takePhoto_onPress = this.takePhoto_onPress.bind(this);
|
||||
|
@ -508,11 +508,16 @@ class Setting extends BaseModel {
|
||||
'folders.sortOrder.reverse': { value: false, type: SettingItemType.Bool, public: true, label: () => _('Reverse sort order'), appTypes: ['cli'] },
|
||||
trackLocation: { value: true, type: SettingItemType.Bool, section: 'note', public: true, label: () => _('Save geo-location with notes') },
|
||||
|
||||
// 2020-10-29: For now disable the beta editor due to
|
||||
// underlying bugs in the TextInput component which we cannot
|
||||
// fix. Also the editor crashes in Android and in some cases in
|
||||
// iOS.
|
||||
// https://discourse.joplinapp.org/t/anyone-using-the-beta-editor-on-ios/11658/9
|
||||
'editor.beta': {
|
||||
value: false,
|
||||
type: SettingItemType.Bool,
|
||||
section: 'note',
|
||||
public: mobilePlatform === 'ios',
|
||||
public: false, // mobilePlatform === 'ios',
|
||||
appTypes: ['mobile'],
|
||||
label: () => 'Opt-in to the editor beta',
|
||||
description: () => 'This beta adds list continuation, Markdown preview, and Markdown shortcuts. If you find bugs, please report them in the Discourse forum.',
|
||||
|
@ -144,8 +144,17 @@ export default class CommandService extends BaseService {
|
||||
return output;
|
||||
}
|
||||
|
||||
public commandNames() {
|
||||
return Object.keys(this.commands_);
|
||||
public commandNames(publicOnly:boolean = false) {
|
||||
if (publicOnly) {
|
||||
const output = [];
|
||||
for (const name in this.commands_) {
|
||||
if (!this.isPublic(name)) continue;
|
||||
output.push(name);
|
||||
}
|
||||
return output;
|
||||
} else {
|
||||
return Object.keys(this.commands_);
|
||||
}
|
||||
}
|
||||
|
||||
public commandByName(name:string, options:CommandByNameOptions = null):Command {
|
||||
@ -230,6 +239,10 @@ export default class CommandService extends BaseService {
|
||||
return stateToWhenClauseContext(this.store_.getState());
|
||||
}
|
||||
|
||||
public isPublic(commandName:string) {
|
||||
return !!this.label(commandName);
|
||||
}
|
||||
|
||||
// When looping on commands and checking their enabled state, the whenClauseContext
|
||||
// should be specified (created using currentWhenClauseContext) to avoid having
|
||||
// to re-create it on each call.
|
||||
|
@ -106,8 +106,9 @@ class DecryptionWorker {
|
||||
if (!('errorHandler' in options)) options.errorHandler = 'log';
|
||||
|
||||
if (this.state_ !== 'idle') {
|
||||
this.logger().debug(`DecryptionWorker: cannot start because state is "${this.state_}"`);
|
||||
return;
|
||||
const msg = `DecryptionWorker: cannot start because state is "${this.state_}"`;
|
||||
this.logger().debug(msg);
|
||||
return { error: new Error(msg) };
|
||||
}
|
||||
|
||||
// Note: the logic below is an optimisation to avoid going through the loop if no master key exists
|
||||
@ -115,7 +116,8 @@ class DecryptionWorker {
|
||||
// "throw" and "dispatch" logic.
|
||||
const loadedMasterKeyCount = await this.encryptionService().loadedMasterKeysCount();
|
||||
if (!loadedMasterKeyCount) {
|
||||
this.logger().info('DecryptionWorker: cannot start because no master key is currently loaded.');
|
||||
const msg = 'DecryptionWorker: cannot start because no master key is currently loaded.';
|
||||
this.logger().info(msg);
|
||||
const ids = await MasterKey.allIds();
|
||||
|
||||
if (ids.length) {
|
||||
@ -130,7 +132,7 @@ class DecryptionWorker {
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
return { error: new Error(msg) };
|
||||
}
|
||||
|
||||
this.logger().info('DecryptionWorker: starting decryption...');
|
||||
|
@ -16,7 +16,6 @@ const defaultKeymapItems = {
|
||||
{ accelerator: 'Cmd+N', command: 'newNote' },
|
||||
{ accelerator: 'Cmd+T', command: 'newTodo' },
|
||||
{ accelerator: 'Cmd+S', command: 'synchronize' },
|
||||
{ accelerator: '', command: 'print' },
|
||||
{ accelerator: 'Cmd+H', command: 'hideApp' },
|
||||
{ accelerator: 'Cmd+Q', command: 'quit' },
|
||||
{ accelerator: 'Cmd+,', command: 'config' },
|
||||
@ -51,7 +50,6 @@ const defaultKeymapItems = {
|
||||
{ accelerator: 'Ctrl+N', command: 'newNote' },
|
||||
{ accelerator: 'Ctrl+T', command: 'newTodo' },
|
||||
{ accelerator: 'Ctrl+S', command: 'synchronize' },
|
||||
{ accelerator: null, command: 'print' },
|
||||
{ accelerator: 'Ctrl+Q', command: 'quit' },
|
||||
{ accelerator: 'Ctrl+Alt+I', command: 'insertTemplate' },
|
||||
{ accelerator: 'Ctrl+C', command: 'textCopy' },
|
||||
@ -103,29 +101,42 @@ export default class KeymapService extends BaseService {
|
||||
super();
|
||||
|
||||
this.lastSaveTime_ = Date.now();
|
||||
|
||||
// By default, initialize for the current platform
|
||||
// Manual initialization allows testing for other platforms
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
public get lastSaveTime():number {
|
||||
return this.lastSaveTime_;
|
||||
}
|
||||
|
||||
public initialize(platform: string = shim.platformName()) {
|
||||
// `additionalDefaultCommandNames` will be added to the default keymap
|
||||
// **except** if they are already in it. Basically this is a mechanism
|
||||
// to add all the commands from the command service to the default
|
||||
// keymap.
|
||||
public initialize(additionalDefaultCommandNames:string[] = [], platform: string = shim.platformName()) {
|
||||
this.platform = platform;
|
||||
|
||||
switch (platform) {
|
||||
case 'darwin':
|
||||
this.defaultKeymapItems = defaultKeymapItems.darwin;
|
||||
this.defaultKeymapItems = defaultKeymapItems.darwin.slice();
|
||||
this.modifiersRegExp = modifiersRegExp.darwin;
|
||||
break;
|
||||
default:
|
||||
this.defaultKeymapItems = defaultKeymapItems.default;
|
||||
this.defaultKeymapItems = defaultKeymapItems.default.slice();
|
||||
this.modifiersRegExp = modifiersRegExp.default;
|
||||
}
|
||||
|
||||
for (const name of additionalDefaultCommandNames) {
|
||||
if (this.defaultKeymapItems.find((item:KeymapItem) => item.command === name)) continue;
|
||||
this.defaultKeymapItems.push({
|
||||
command: name,
|
||||
accelerator: null,
|
||||
});
|
||||
}
|
||||
|
||||
this.resetKeymap();
|
||||
}
|
||||
|
||||
// Reset keymap back to its default values
|
||||
public resetKeymap() {
|
||||
this.keymap = {};
|
||||
for (let i = 0; i < this.defaultKeymapItems.length; i++) {
|
||||
// Keep the original defaultKeymapItems array untouched
|
||||
@ -140,7 +151,9 @@ export default class KeymapService extends BaseService {
|
||||
if (await shim.fsDriver().exists(customKeymapPath)) {
|
||||
this.logger().info(`KeymapService: Loading keymap from file: ${customKeymapPath}`);
|
||||
|
||||
const customKeymapFile = await shim.fsDriver().readFile(customKeymapPath, 'utf-8');
|
||||
const customKeymapFile = (await shim.fsDriver().readFile(customKeymapPath, 'utf-8')).trim();
|
||||
if (!customKeymapFile) return;
|
||||
|
||||
// Custom keymaps are supposed to contain an array of keymap items
|
||||
this.overrideKeymap(JSON.parse(customKeymapFile));
|
||||
}
|
||||
@ -183,8 +196,8 @@ export default class KeymapService extends BaseService {
|
||||
|
||||
if (!commandName) throw new Error('Cannot register an accelerator without a command name');
|
||||
|
||||
const validatedAccelerator = this.convertToPlatform(accelerator);
|
||||
this.validateAccelerator(validatedAccelerator);
|
||||
const validatedAccelerator = accelerator ? this.convertToPlatform(accelerator) : null;
|
||||
if (validatedAccelerator) this.validateAccelerator(validatedAccelerator);
|
||||
|
||||
this.keymap[commandName] = {
|
||||
command: commandName,
|
||||
@ -264,7 +277,7 @@ export default class KeymapService extends BaseService {
|
||||
// Throws whenever there are duplicate Accelerators used in the keymap
|
||||
this.validateKeymap();
|
||||
} catch (err) {
|
||||
this.initialize(); // Discard all the changes if there are any issues
|
||||
this.resetKeymap(); // Discard all the changes if there are any issues
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@ -339,7 +352,10 @@ export default class KeymapService extends BaseService {
|
||||
|
||||
public domToElectronAccelerator(event: KeyboardEvent<HTMLDivElement>) {
|
||||
const parts = [];
|
||||
const { key, ctrlKey, metaKey, altKey, shiftKey } = event;
|
||||
|
||||
// We use the "keyCode" and not "key" because the modifier keys
|
||||
// would change the "key" value. eg "Option+U" would give "º" as a key instead of "U"
|
||||
const { keyCode, ctrlKey, metaKey, altKey, shiftKey } = event;
|
||||
|
||||
// First, the modifiers
|
||||
if (ctrlKey) parts.push('Ctrl');
|
||||
@ -355,7 +371,7 @@ export default class KeymapService extends BaseService {
|
||||
}
|
||||
|
||||
// Finally, the key
|
||||
const electronKey = KeymapService.domToElectronKey(key);
|
||||
const electronKey = KeymapService.domToElectronKey(String.fromCharCode(keyCode));
|
||||
if (electronKey) parts.push(electronKey);
|
||||
|
||||
return parts.join('+');
|
||||
|
@ -10,12 +10,13 @@ const { execCommand, githubUsername } = require('./tool-utils.js');
|
||||
|
||||
// From https://stackoverflow.com/a/6234804/561309
|
||||
function escapeHtml(unsafe) {
|
||||
// We only escape <> as this is enough for Markdown
|
||||
return unsafe
|
||||
.replace(/&/g, '&')
|
||||
// .replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
.replace(/>/g, '>');
|
||||
// .replace(/"/g, '"')
|
||||
// .replace(/'/g, ''');
|
||||
}
|
||||
|
||||
async function gitLog(sinceTag) {
|
||||
|
Loading…
Reference in New Issue
Block a user