Skip to content

Commit 3370b0f

Browse files
ProfBramblewewoor
andauthored
feat(menubar): add menu bar methods to service and support shortcut keys (#298)
* feat: menu bar add new file function * feat: add encapsulated event state automata * feat: add menu bar action to menu bar controller * feat: define menu function and export operation id * feat: register view shortcut * feat: add key code string constant * feat: register the view method in the editor service * feat: register select all keyboard listener class * feat: register copy line up keyboard listener class * refactor: register undo and redo to keybinding * perf: extract function to keybinding * feat: add new file to keybinding * feat: use monaco service to get menu functions * feat: register menubar onSelect to subscribers * refactor: update the MenuBarService (#292) * refactor: remove addRootMenu method, and rename initMenu to initMenus * docs: add comments for the IMenuBarService interface * perf: move create file or folder function in service * feat: add new file to keybinding * feat: register menubar onSelect to subscribers * fix: increase call rigor * feat: add story of open any file on disk * feat: support file highlighting * feat: register the view method in the editor service * perf: extract function to keybinding * feat: add new file to keybinding * perf: better type description Co-authored-by: Ziv <wewoor@gmail.com>
1 parent fa5bae6 commit 3370b0f

File tree

13 files changed

+378
-75
lines changed

13 files changed

+378
-75
lines changed

src/controller/editor.tsx

-19
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ import {
1414
EDITOR_MENU_SHOW_OPENEDITORS,
1515
EDITOR_MENU_SPILIT,
1616
} from 'mo/model/workbench/editor';
17-
import { undoRedoMenu } from 'mo/model/workbench/menuBar';
1817
import { Controller } from 'mo/react/controller';
19-
2018
import { IMenuItemProps } from 'mo/components/menu';
2119
import { STATUS_EDITOR_INFO } from 'mo/model/workbench/statusBar';
2220
import { IMonacoEditorProps } from 'mo/components/monaco';
@@ -161,7 +159,6 @@ export class EditorController extends Controller implements IEditorController {
161159
if (!editorInstance) return;
162160

163161
this.initEditorEvents(editorInstance, groupId);
164-
this.registerActions(editorInstance);
165162
this.editorService.updateGroup(groupId, {
166163
editorInstance: editorInstance,
167164
});
@@ -178,22 +175,6 @@ export class EditorController extends Controller implements IEditorController {
178175
);
179176
};
180177

181-
// TODO: Remove the below action register ?, because of the monaco Editor have integrated the undo/redo action
182-
private registerActions = (editorInstance) => {
183-
undoRedoMenu.forEach(({ id, label }) => {
184-
editorInstance?.addAction({
185-
id,
186-
label,
187-
run: () => {
188-
editorInstance!.focus();
189-
if (!document.execCommand(id)) {
190-
editorInstance?.getModel()?.[id]();
191-
}
192-
},
193-
});
194-
});
195-
};
196-
197178
public onClickActions = (action: IEditorActionsProps) => {
198179
const { current } = this.editorService.getState();
199180
if (!current) return;

src/controller/explorer/folderTree.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ import {
1515
OPEN_TO_SIDE_COMMAND_ID,
1616
FolderTreeEvent,
1717
FileTypes,
18+
FileType,
1819
} from 'mo/model';
1920
import { FolderTreeService, IFolderTreeService } from 'mo/services';
2021

2122
export interface IFolderTreeController {
22-
readonly createTreeNode: (type: keyof typeof FileTypes) => void;
23+
readonly createTreeNode: (type: FileType) => void;
2324
readonly onClickContextMenu: (
2425
contextMenu: IMenuItemProps,
2526
treeNode: ITreeNodeItemProps
@@ -68,7 +69,7 @@ export class FolderTreeController
6869
return menus;
6970
};
7071

71-
public createTreeNode = (type: keyof typeof FileTypes) => {
72+
public createTreeNode = (type: FileType) => {
7273
const folderTreeState = this.folderTreeService.getState();
7374
const { data, current } = folderTreeState?.folderTree || {};
7475
// The current selected node id or the first root node

src/controller/menuBar.ts

+56-32
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@ import 'reflect-metadata';
22
import { container, singleton } from 'tsyringe';
33
import { IActivityBarItem, IMenuBarItem } from 'mo/model';
44
import {
5-
MENU_FILE_REDO,
6-
MENU_FILE_UNDO,
5+
ACTION_QUICK_SELECT_ALL,
6+
ACTION_QUICK_COPY_LINE_UP,
7+
ACTION_QUICK_COMMAND,
8+
ACTION_QUICK_UNDO,
9+
ACTION_QUICK_REDO,
10+
ACTION_QUICK_CREATE_FILE,
11+
} from 'mo/model/keybinding';
12+
import {
13+
MENU_QUICK_COMMAND,
714
MENU_VIEW_ACTIVITYBAR,
815
MENU_VIEW_MENUBAR,
916
MENU_VIEW_PANEL,
1017
MENU_VIEW_STATUSBAR,
1118
} from 'mo/model/workbench/menuBar';
19+
import { MenuBarEvent } from 'mo/model/workbench/menuBar';
1220
import { Controller } from 'mo/react/controller';
1321
import {
14-
EditorService,
15-
IEditorService,
1622
IMenuBarService,
1723
ILayoutService,
1824
MenuBarService,
@@ -36,52 +42,58 @@ export interface IMenuBarController {
3642
export class MenuBarController
3743
extends Controller
3844
implements IMenuBarController {
39-
private readonly editorService: IEditorService;
4045
private readonly menuBarService: IMenuBarService;
4146
private readonly layoutService: ILayoutService;
4247
private readonly monacoService: IMonacoService;
48+
private automation = {
49+
[ACTION_QUICK_CREATE_FILE]: () => this.createFile(),
50+
[ACTION_QUICK_UNDO]: () => this.undo(),
51+
[ACTION_QUICK_REDO]: () => this.redo(),
52+
[ACTION_QUICK_SELECT_ALL]: () => this.selectAll(),
53+
[ACTION_QUICK_COPY_LINE_UP]: () => this.copyLineUp(),
54+
[MENU_VIEW_ACTIVITYBAR]: () => this.updateActivityBar(),
55+
[MENU_VIEW_MENUBAR]: () => this.updateMenuBar(),
56+
[MENU_VIEW_STATUSBAR]: () => this.updateStatusBar(),
57+
[MENU_QUICK_COMMAND]: () => this.gotoQuickCommand(),
58+
[ID_SIDE_BAR]: () => this.updateSideBar(),
59+
[MENU_VIEW_PANEL]: () => this.updatePanel(),
60+
};
4361

4462
constructor() {
4563
super();
46-
this.editorService = container.resolve(EditorService);
4764
this.menuBarService = container.resolve(MenuBarService);
4865
this.layoutService = container.resolve(LayoutService);
4966
this.monacoService = container.resolve(MonacoService);
5067
}
5168

5269
public readonly onClick = (event: React.MouseEvent, item: IMenuBarItem) => {
53-
const menuId = item.id;
54-
switch (menuId) {
55-
case MENU_FILE_UNDO:
56-
this.undo();
57-
break;
58-
case MENU_FILE_REDO:
59-
this.redo();
60-
break;
61-
case MENU_VIEW_ACTIVITYBAR:
62-
this.updateActivityBar();
63-
break;
64-
case MENU_VIEW_MENUBAR:
65-
this.updateMenuBar();
66-
break;
67-
case MENU_VIEW_STATUSBAR:
68-
this.updateStatusBar();
69-
break;
70-
case ID_SIDE_BAR:
71-
this.updateSideBar();
72-
break;
73-
case MENU_VIEW_PANEL:
74-
this.updatePanel();
75-
break;
76-
}
70+
const menuId = item.id || '';
71+
72+
/**
73+
* TODO: Two issues remain to be addressed
74+
* 1、the default event is executed twice
75+
* 2、we have no way of knowing whether user-defined events are executed internally
76+
*/
77+
this.emit(MenuBarEvent.onSelect, menuId);
78+
this.automation[menuId]?.();
79+
};
80+
81+
public createFile = () => {
82+
this.monacoService.commandService.executeCommand(
83+
ACTION_QUICK_CREATE_FILE
84+
);
7785
};
7886

7987
public undo = () => {
80-
this.editorService.editorInstance?.getAction('undo').run();
88+
this.monacoService.commandService.executeCommand(ACTION_QUICK_UNDO);
8189
};
8290

8391
public redo = () => {
84-
this.editorService.editorInstance?.getAction('redo').run();
92+
this.monacoService.commandService.executeCommand(ACTION_QUICK_REDO);
93+
};
94+
95+
public gotoQuickCommand = () => {
96+
this.monacoService.commandService.executeCommand(ACTION_QUICK_COMMAND);
8597
};
8698

8799
public updateActivityBar = () => {
@@ -94,6 +106,18 @@ export class MenuBarController
94106
});
95107
};
96108

109+
public selectAll = () => {
110+
this.monacoService.commandService.executeCommand(
111+
ACTION_QUICK_SELECT_ALL
112+
);
113+
};
114+
115+
public copyLineUp = () => {
116+
this.monacoService.commandService.executeCommand(
117+
ACTION_QUICK_COPY_LINE_UP
118+
);
119+
};
120+
97121
public updateMenuBar = () => {
98122
this.layoutService.setMenuBarHidden();
99123
const {

src/extensions/keybinding/index.ts

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import { CommandQuickAccessViewAction } from 'mo/monaco/quickAccessViewAction';
66
import { SelectColorThemeAction } from 'mo/monaco/selectColorThemeAction';
77
import { CommandQuickSideBarViewAction } from 'mo/monaco/quickToggleSideBarAction';
88
import { QuickTogglePanelAction } from 'mo/monaco/quickTogglePanelAction';
9+
import { QuickSelectAllAction } from 'mo/monaco/quickSelectAllAction';
10+
import { QuickCopyLineUp } from 'mo/monaco/quickCopyLineUp';
11+
import { QuickRedo } from 'mo/monaco/quickRedo';
12+
import { QuickUndo } from 'mo/monaco/quickUndo';
13+
import { QuickCreateFile } from 'mo/monaco/quickCreateFile';
914

1015
export const ExtendsKeybinding: IExtension = {
1116
activate(extensionCtx: IExtensionService) {
@@ -15,5 +20,10 @@ export const ExtendsKeybinding: IExtension = {
1520
extensionCtx.registerAction(SelectLocaleAction);
1621
extensionCtx.registerAction(CommandQuickSideBarViewAction);
1722
extensionCtx.registerAction(QuickTogglePanelAction);
23+
extensionCtx.registerAction(QuickSelectAllAction);
24+
extensionCtx.registerAction(QuickCopyLineUp);
25+
extensionCtx.registerAction(QuickUndo);
26+
extensionCtx.registerAction(QuickRedo);
27+
extensionCtx.registerAction(QuickCreateFile);
1828
},
1929
};

src/model/keybinding.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export const KeyCodeString: Partial<{ [key in KeyCode]: string }> = {
55
[KeyCode.Backspace]: '⌫',
66
[KeyCode.Tab]: '⇥',
77
[KeyCode.Enter]: '↩︎',
8+
[KeyCode.PageUp]: '↑',
9+
[KeyCode.PageDown]: '↓',
810
[KeyCode.KEY_0]: '0',
911
[KeyCode.KEY_1]: '1',
1012
[KeyCode.KEY_2]: '2',
@@ -62,8 +64,15 @@ export interface ISimpleKeybinding {
6264
keyCode: KeyCode;
6365
}
6466

67+
export const ACTION_QUICK_COMMAND = 'editor.action.quickCommand';
68+
export const ACTION_QUICK_SELECT_ALL = 'editor.action.quickSelectAll';
69+
export const ACTION_QUICK_COPY_LINE_UP = 'editor.action.copyLinesUpAction';
70+
export const ACTION_QUICK_UNDO = 'editor.action.undo';
71+
export const ACTION_QUICK_REDO = 'editor.action.redo';
72+
73+
export const ACTION_QUICK_CREATE_FILE = 'workbench.action.quickCreateFile';
74+
export const ACTION_QUICK_CREATE_FOLDER = 'workbench.action.quickCreateFolder';
6575
export const ACTION_QUICK_ACCESS_SETTINGS =
6676
'workbench.action.quickAccessSettings';
67-
export const ACTION_QUICK_COMMAND = 'editor.action.quickCommand';
6877
export const ACTION_SELECT_THEME = 'workbench.action.selectTheme';
6978
export const ACTION_SELECT_LOCALE = 'workbench.action.selectLocale';

src/model/workbench/menuBar.ts

+19-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import * as React from 'react';
22
import { localize } from 'mo/i18n/localize';
33
import { ID_SIDE_BAR } from 'mo/common/id';
4+
import {
5+
ACTION_QUICK_SELECT_ALL,
6+
ACTION_QUICK_COPY_LINE_UP,
7+
ACTION_QUICK_UNDO,
8+
ACTION_QUICK_REDO,
9+
ACTION_QUICK_CREATE_FILE,
10+
} from 'mo/model/keybinding';
411

512
/**
613
* The activity bar event definition
@@ -9,7 +16,7 @@ export enum MenuBarEvent {
916
/**
1017
* Selected an activity bar
1118
*/
12-
onClick = 'menuBar.onClick',
19+
onSelect = 'menuBar.onSelect',
1320
}
1421

1522
export interface IMenuBarItem {
@@ -23,8 +30,10 @@ export interface IMenuBar {
2330
data?: IMenuBarItem[];
2431
}
2532

26-
export const MENU_FILE_UNDO = 'undo';
27-
export const MENU_FILE_REDO = 'redo';
33+
export const MENU_FILE_OPEN = 'openFile';
34+
35+
export const MENU_QUICK_COMMAND = 'editor.action.quickCommand';
36+
2837
export const MENU_VIEW_MENUBAR = 'workbench.action.showMenuBar';
2938
export const MENU_VIEW_ACTIVITYBAR = 'workbench.action.showActivityBar';
3039
export const MENU_VIEW_STATUSBAR = 'workbench.action.showStatusBar';
@@ -37,11 +46,11 @@ export function builtInMenuBarData() {
3746
name: localize('menu.file', 'File'),
3847
data: [
3948
{
40-
id: 'New File',
49+
id: ACTION_QUICK_CREATE_FILE,
4150
name: localize('menu.newFile', 'New File'),
4251
},
4352
{
44-
id: 'OpenFile',
53+
id: MENU_FILE_OPEN,
4554
name: localize('menu.open', 'Open'),
4655
},
4756
],
@@ -51,11 +60,11 @@ export function builtInMenuBarData() {
5160
name: localize('menu.edit', 'Edit'),
5261
data: [
5362
{
54-
id: MENU_FILE_UNDO,
63+
id: ACTION_QUICK_UNDO,
5564
name: localize('menu.undo', 'Undo'),
5665
},
5766
{
58-
id: MENU_FILE_REDO,
67+
id: ACTION_QUICK_REDO,
5968
name: localize('menu.redo', 'Redo'),
6069
},
6170
],
@@ -65,11 +74,11 @@ export function builtInMenuBarData() {
6574
name: localize('menu.selection', 'Selection'),
6675
data: [
6776
{
68-
id: 'SelectAll',
77+
id: ACTION_QUICK_SELECT_ALL,
6978
name: localize('menu.selectAll', 'Select All'),
7079
},
7180
{
72-
id: 'CopyLineUp',
81+
id: ACTION_QUICK_COPY_LINE_UP,
7382
name: localize('menu.copyLineUp', 'Copy Line Up'),
7483
},
7584
],
@@ -79,7 +88,7 @@ export function builtInMenuBarData() {
7988
name: localize('menu.view', 'View'),
8089
data: [
8190
{
82-
id: 'Command Palette',
91+
id: MENU_QUICK_COMMAND,
8392
name: localize('menu.commandPalette', 'Command Palette'),
8493
},
8594
{
@@ -148,16 +157,6 @@ export function builtInMenuBarData() {
148157
];
149158
}
150159

151-
export const undoRedoMenu = [
152-
{
153-
id: MENU_FILE_UNDO,
154-
label: localize('menu.undo', 'Undo'),
155-
},
156-
{
157-
id: MENU_FILE_REDO,
158-
label: localize('menu.redo', 'Redo'),
159-
},
160-
];
161160
export class MenuBarModel implements IMenuBar {
162161
public data: IMenuBarItem[];
163162

src/monaco/quickCopyLineUp.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'reflect-metadata';
2+
import { localize } from 'mo/i18n/localize';
3+
import { KeyMod, KeyCode } from 'mo/monaco';
4+
import { EditorService, IEditorService } from 'mo/services';
5+
import { container } from 'tsyringe';
6+
import { Action2, KeybindingWeight } from './common';
7+
import { ACTION_QUICK_COPY_LINE_UP } from 'mo/model/keybinding';
8+
9+
export class QuickCopyLineUp extends Action2 {
10+
static readonly ID = ACTION_QUICK_COPY_LINE_UP;
11+
static readonly LABEL = localize('menu.copyLineUp', 'Copy Line Up');
12+
static readonly DESC = 'Copy Line Up';
13+
private readonly editorService: IEditorService;
14+
15+
constructor() {
16+
super({
17+
id: QuickCopyLineUp.ID,
18+
title: {
19+
value: QuickCopyLineUp.LABEL,
20+
original: QuickCopyLineUp.DESC,
21+
},
22+
label: QuickCopyLineUp.LABEL,
23+
alias: QuickCopyLineUp.DESC,
24+
f1: true,
25+
keybinding: {
26+
when: undefined,
27+
weight: KeybindingWeight.WorkbenchContrib,
28+
// eslint-disable-next-line new-cap
29+
primary: KeyMod.Alt | KeyMod.Shift | KeyCode.PageUp,
30+
},
31+
});
32+
this.editorService = container.resolve(EditorService);
33+
}
34+
35+
run() {
36+
this.editorService.editorInstance
37+
?.getAction(ACTION_QUICK_COPY_LINE_UP)
38+
.run();
39+
}
40+
}

0 commit comments

Comments
 (0)