Browse Source

feat: add Substitutions menu roles on macOS (#32024)

Mitchell Cohen 3 years ago
parent
commit
5af6b898d9

+ 5 - 1
docs/api/menu-item.md

@@ -14,7 +14,7 @@ See [`Menu`](menu.md) for examples.
     * `menuItem` MenuItem
     * `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
     * `event` [KeyboardEvent](structures/keyboard-event.md)
-  * `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
+  * `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, 'showSubstitutions', 'toggleSmartQuotes', 'toggleSmartDashes', 'toggleTextReplacement', `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
     `click` property will be ignored. See [roles](#roles).
   * `type` string (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
     `radio`.
@@ -100,6 +100,10 @@ The following additional roles are available on _macOS_:
 * `hide` - Map to the `hide` action.
 * `hideOthers` - Map to the `hideOtherApplications` action.
 * `unhide` - Map to the `unhideAllApplications` action.
+* `showSubstitutions` - Map to the `orderFrontSubstitutionsPanel` action.
+* `toggleSmartQuotes` - Map to the `toggleAutomaticQuoteSubstitution` action.
+* `toggleSmartDashes` - Map to the `toggleAutomaticDashSubstitution` action.
+* `toggleTextReplacement` - Map to the `toggleAutomaticTextReplacement` action.
 * `startSpeaking` - Map to the `startSpeaking` action.
 * `stopSpeaking` - Map to the `stopSpeaking` action.
 * `front` - Map to the `arrangeInFront` action.

+ 24 - 1
lib/browser/api/menu-item-roles.ts

@@ -5,7 +5,8 @@ const isWindows = process.platform === 'win32';
 const isLinux = process.platform === 'linux';
 
 type RoleId = 'about' | 'close' | 'copy' | 'cut' | 'delete' | 'forcereload' | 'front' | 'help' | 'hide' | 'hideothers' | 'minimize' |
-  'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' | 'startspeaking' | 'stopspeaking' |
+  'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' |
+  'showsubstitutions' | 'togglesmartquotes' | 'togglesmartdashes' | 'toggletextreplacement' | 'startspeaking' | 'stopspeaking' |
   'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'togglespellchecker' |
   'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu' | 'sharemenu'
 interface Role {
@@ -133,6 +134,18 @@ export const roleList: Record<RoleId, Role> = {
   clearrecentdocuments: {
     label: 'Clear Menu'
   },
+  showsubstitutions: {
+    label: 'Show Substitutions'
+  },
+  togglesmartquotes: {
+    label: 'Smart Quotes'
+  },
+  togglesmartdashes: {
+    label: 'Smart Dashes'
+  },
+  toggletextreplacement: {
+    label: 'Text Replacement'
+  },
   startspeaking: {
     label: 'Start Speaking'
   },
@@ -237,6 +250,16 @@ export const roleList: Record<RoleId, Role> = {
         { role: 'delete' },
         { role: 'selectAll' },
         { type: 'separator' },
+        {
+          label: 'Substitutions',
+          submenu: [
+            { role: 'showSubstitutions' },
+            { type: 'separator' },
+            { role: 'toggleSmartQuotes' },
+            { role: 'toggleSmartDashes' },
+            { role: 'toggleTextReplacement' }
+          ]
+        },
         {
           label: 'Speech',
           submenu: [

+ 4 - 0
shell/browser/ui/cocoa/electron_menu_controller.mm

@@ -50,6 +50,10 @@ Role kRolesMap[] = {
     {@selector(delete:), "delete"},
     {@selector(pasteAndMatchStyle:), "pasteandmatchstyle"},
     {@selector(selectAll:), "selectall"},
+    {@selector(orderFrontSubstitutionsPanel:), "showsubstitutions"},
+    {@selector(toggleAutomaticQuoteSubstitution:), "togglesmartquotes"},
+    {@selector(toggleAutomaticDashSubstitution:), "togglesmartdashes"},
+    {@selector(toggleAutomaticTextReplacement:), "toggletextreplacement"},
     {@selector(startSpeaking:), "startspeaking"},
     {@selector(stopSpeaking:), "stopspeaking"},
     {@selector(performMiniaturize:), "minimize"},

+ 9 - 3
spec-main/api-menu-item-spec.ts

@@ -351,9 +351,15 @@ describe('MenuItems', () => {
         expect(item.submenu!.items[7].role).to.equal('delete');
         expect(item.submenu!.items[8].role).to.equal('selectall');
         expect(item.submenu!.items[9].type).to.equal('separator');
-        expect(item.submenu!.items[10].label).to.equal('Speech');
-        expect(item.submenu!.items[10].submenu!.items[0].role).to.equal('startspeaking');
-        expect(item.submenu!.items[10].submenu!.items[1].role).to.equal('stopspeaking');
+        expect(item.submenu!.items[10].label).to.equal('Substitutions');
+        expect(item.submenu!.items[10].submenu!.items[0].role).to.equal('showsubstitutions');
+        expect(item.submenu!.items[10].submenu!.items[1].type).to.equal('separator');
+        expect(item.submenu!.items[10].submenu!.items[2].role).to.equal('togglesmartquotes');
+        expect(item.submenu!.items[10].submenu!.items[3].role).to.equal('togglesmartdashes');
+        expect(item.submenu!.items[10].submenu!.items[4].role).to.equal('toggletextreplacement');
+        expect(item.submenu!.items[11].label).to.equal('Speech');
+        expect(item.submenu!.items[11].submenu!.items[0].role).to.equal('startspeaking');
+        expect(item.submenu!.items[11].submenu!.items[1].role).to.equal('stopspeaking');
       } else {
         expect(item.submenu!.items[6].role).to.equal('delete');
         expect(item.submenu!.items[7].type).to.equal('separator');