Skip to content

Commit

Permalink
fix: improve editor actions (#234)
Browse files Browse the repository at this point in the history
* refactor: rename update actions and create a new update actions function

* fix: improve editor actions

* fix: improve interface name

* fix: rename ellipsisActions
  • Loading branch information
mortalYoung authored Jul 15, 2021
1 parent 1dfee56 commit 443d4da
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 59 deletions.
30 changes: 26 additions & 4 deletions src/controller/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
EDITOR_MENU_CLOSE_TO_RIGHT,
EDITOR_MENU_CLOSE_TO_LEFT,
EDITOR_MENU_CLOSE_ALL,
IEditorActionsProps,
EDITOR_MENU_SHOW_OPENEDITORS,
EDITOR_MENU_SPILIT,
} from 'mo/model/workbench/editor';
import { undoRedoMenu } from 'mo/model/workbench/menuBar';
import { Controller } from 'mo/react/controller';
Expand Down Expand Up @@ -47,7 +50,7 @@ export interface IEditorController {
) => void;
onMoveTab?: <T = any>(updateTabs: IEditorTab<T>[], group: number) => void;
onSelectTab?: (tabId: string, group: number) => void;
onSplitEditorRight?: () => void;
onClickActions: (action: IEditorActionsProps) => void;
onUpdateEditorIns?: (editorInstance: any, groupId: number) => void;
onPaneSizeChange?: (newSize: number) => void;
}
Expand Down Expand Up @@ -190,9 +193,28 @@ export class EditorController extends Controller implements IEditorController {
});
};

public onSplitEditorRight = () => {
this.editorService.cloneGroup();
this.emit(EditorEvent.OnSplitEditorRight);
public onClickActions = (action: IEditorActionsProps) => {
const { current } = this.editorService.getState();
if (!current) return;

switch (action.id) {
case EDITOR_MENU_CLOSE_ALL: {
this.onCloseAll(current.id!);
break;
}
case EDITOR_MENU_SHOW_OPENEDITORS: {
// TODO
break;
}
case EDITOR_MENU_SPILIT: {
this.editorService.cloneGroup();
this.emit(EditorEvent.OnSplitEditorRight);
break;
}
default: {
this.emit(EditorEvent.onActionsClick, action.id, current);
}
}
};

public onPaneSizeChange = (newSize) => {
Expand Down
1 change: 1 addition & 0 deletions src/extensions/theme-defaults/themes/dark_defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"inputValidation.warningBorder": "#B89500",
"inputValidation.errorBackground": "#5A1D1D",
"inputValidation.errorBorder": "#BE1100",
"icon.foreground": "#C5C5C5",
"settings.textInputBackground": "#292929",
"settings.numberInputBackground": "#292929",
"menu.background": "#252526",
Expand Down
1 change: 1 addition & 0 deletions src/extensions/theme-defaults/themes/light_defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"inputValidation.warningBorder": "#B89500",
"inputValidation.errorBackground": "#F2DEDE",
"inputValidation.errorBorder": "#BE1100",
"icon.foreground": "#424242",
"searchEditor.textInputBorder": "#CECECE",
"diffEditor.insertedTextBackground": "#9bb95533",
"diffEditor.removedTextBackground": "#ff000033",
Expand Down
25 changes: 20 additions & 5 deletions src/model/workbench/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,19 @@ interface BuiltInEditorTabDataType {
modified?: boolean;
}

export interface IEditorActionsProps extends IMenuItemProps {
id: string;
/**
* Mark the action placed in More menus or outer
*/
place?: 'outer';
}

export interface IEditorTab<T = BuiltInEditorTabDataType> extends ITabProps<T> {
breadcrumb?: IBreadcrumbItemProps[];
}
export interface IEditorAction {
actions?: IMenuItemProps[];
actions?: IEditorActionsProps[];
menu?: IMenuItemProps[];
}
export interface IEditorGroup<E = any, T = any> extends ITabsProps<T> {
Expand All @@ -37,7 +45,7 @@ export interface IEditorGroup<E = any, T = any> extends ITabsProps<T> {
* Current editor group tab
*/
tab?: IEditorTab<T>;
actions?: IMenuItemProps[];
actions?: IEditorActionsProps[];
menu?: IMenuItemProps[];
editorInstance?: E;
}
Expand All @@ -57,6 +65,7 @@ export const EDITOR_MENU_CLOSE_OTHERS = 'editor.closeOthers';
export const EDITOR_MENU_CLOSE_SAVED = 'editor.closeSaved';
export const EDITOR_MENU_CLOSE = 'editor.close';
export const EDITOR_MENU_SHOW_OPENEDITORS = 'editor.showOpenEditors';
export const EDITOR_MENU_SPILIT = 'editor.split';

export function getBaseMenu() {
return [
Expand All @@ -67,8 +76,14 @@ export function getBaseMenu() {
];
}

export function getEditorInitialActions(): IMenuItemProps[] {
export function getEditorInitialActions(): IEditorActionsProps[] {
return [
{
id: EDITOR_MENU_SPILIT,
name: 'Split Editor Right',
icon: 'split-horizontal',
place: 'outer',
},
{
id: EDITOR_MENU_SHOW_OPENEDITORS,
name: 'Show Opened Editors',
Expand Down Expand Up @@ -103,15 +118,15 @@ export class EditorGroupModel<E = any, T = any> implements IEditorGroup<E, T> {
id: number;
tab: IEditorTab<T>;
data: IEditorTab<T>[];
actions: IMenuItemProps[];
actions: IEditorActionsProps[];
menu: IMenuItemProps[];
editorInstance: E | undefined;

constructor(
id: number,
tab: IEditorTab<T>,
data: IEditorTab<T>[],
actions: IMenuItemProps[] = getEditorInitialActions(),
actions: IEditorActionsProps[] = getEditorInitialActions(),
menu: IMenuItemProps[] = getEditorInitialMenu(),
editorInstance?: E
) {
Expand Down
43 changes: 36 additions & 7 deletions src/services/workbench/editorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
IEditorTab,
EditorEvent,
getEditorInitialActions,
IEditorActionsProps,
} from 'mo/model';
import { searchById } from '../helper';
import { editor as monacoEditor, Uri } from 'mo/monaco';
Expand Down Expand Up @@ -71,9 +72,13 @@ export interface IEditorService extends Component<IEditor> {
setActive(groupId: number, tabId: string);
updateGroup(groupId, groupValues: IEditorGroup): void;
/**
* Update actions in group
* Set default actions when create a new group
*/
updateGroupActions(actions: IMenuItemProps[]): void;
setDefaultActions(actions: IEditorActionsProps[]): void;
/**
* Update actions in specific group
*/
updateActions(actions: IMenuItemProps[], groupId?: number): void;
updateCurrentGroup(currentValues): void;
/**
* The Instance of Editor
Expand All @@ -85,11 +90,11 @@ export class EditorService
extends Component<IEditor>
implements IEditorService {
protected state: IEditor;
protected groupActions: IMenuItemProps[];
protected defaultActions: IEditorActionsProps[];
constructor() {
super();
this.state = container.resolve(EditorModel);
this.groupActions = getEditorInitialActions();
this.defaultActions = getEditorInitialActions();
}

private disposeModel(tabs: IEditorTab | IEditorTab[]) {
Expand All @@ -104,8 +109,8 @@ export class EditorService
return groups.some((group) => this.getTabById(tabId, group));
}

public updateGroupActions(actions: IMenuItemProps[]): void {
this.groupActions = actions;
public setDefaultActions(actions: IEditorActionsProps[]): void {
this.defaultActions = actions;
}

public setEntry(component: React.ReactNode) {
Expand All @@ -114,6 +119,30 @@ export class EditorService
});
}

public updateActions = (actions: IMenuItemProps[], groupId?: number) => {
const { current, groups: rawGroups } = this.getState();
if (!current) return;

const groups = rawGroups?.concat() || [];
const targetGroup = groups.find(searchById(groupId || current.id));

if (targetGroup) {
const newActions = targetGroup.actions?.concat() || [];
newActions.forEach((action) => {
const target = actions.find((item) => item.id === action.id);
if (target) {
Object.assign(action, target);
}
});
targetGroup.actions = newActions;

this.setState({
current: targetGroup.id === current.id ? targetGroup : current,
groups,
});
}
};

public getTabById<T>(
tabId: string,
group: IEditorGroup
Expand Down Expand Up @@ -378,7 +407,7 @@ export class EditorService
groups.length + 1,
tab,
[tab],
this.groupActions
this.defaultActions
);
groups.push(group);
}
Expand Down
110 changes: 73 additions & 37 deletions src/workbench/editor/action.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,67 @@
import * as React from 'react';
import { memo, useCallback } from 'react';
import { memo } from 'react';
import { Icon } from 'mo/components/icon';
import { Menu } from 'mo/components/menu';
import { DropDown, DropDownRef } from 'mo/components/dropdown';
import { IEditorAction } from 'mo/model';
import { groupActionsClassName, groupActionsItemClassName } from './base';
import { IEditorActionsProps, IEditorAction } from 'mo/model';
import {
groupActionItemDisabledClassName,
groupActionsClassName,
groupActionsItemClassName,
} from './base';
import { IEditorController } from 'mo/controller/editor';
import { classNames } from 'mo/common/className';

export interface IEditorActionProps extends IEditorAction {
isActiveGroup: boolean;
}

const MAX_ACTIONS_LENGTH = 6;

function splitActions(actions: IEditorActionsProps[]) {
const outerActions: IEditorActionsProps[] = [];
const innerActions: IEditorActionsProps[] = [];

actions.forEach((action) => {
if (action.place === 'outer') {
outerActions.push(action);
} else {
innerActions.push(action);
}
});

if (outerActions.length > MAX_ACTIONS_LENGTH) {
const surplusActions = outerActions.splice(
0,
MAX_ACTIONS_LENGTH - outerActions.length
);

innerActions.concat(surplusActions);
}

return [outerActions, innerActions];
}

function EditorAction(props: IEditorActionProps & IEditorController) {
const {
actions = [],
isActiveGroup = false,
onClickContextMenu,
onSplitEditorRight,
} = props;
const { actions = [], isActiveGroup = false, onClickActions } = props;
const [outer, inner] = splitActions(actions);

const childRef = React.useRef<DropDownRef>(null);

const handleOnMenuClick = (e: React.MouseEvent, item) => {
onClickContextMenu?.(e, item);
(childRef.current as any)!.dispose();
const handleOnMenuClick = (_, item) => {
onClickActions(item);
childRef.current?.dispose();
};

const handleActionsClick = (action) => {
onClickActions(action);
};

const overlay =
actions.length > 0 ? (
inner.length > 0 ? (
<Menu
style={{ width: 200 }}
data={actions}
data={inner}
onClick={handleOnMenuClick}
/>
) : (
Expand All @@ -44,33 +75,38 @@ function EditorAction(props: IEditorActionProps & IEditorController) {
</span>
);

const handleSplitEditor = useCallback(
(e: React.MouseEvent) => {
onSplitEditorRight?.();
},
[actions]
);
return (
<div className={groupActionsClassName}>
{isActiveGroup ? (
<div
onClick={handleSplitEditor}
{isActiveGroup &&
outer.map((action) => (
<div
key={action.id}
onClick={() => handleActionsClick(action)}
className={classNames(
groupActionsItemClassName,
action.disabled && groupActionItemDisabledClassName
)}
title={action.name?.toString()}
>
{action.icon ? (
<Icon type={action.icon} />
) : (
action.name
)}
</div>
))}
{Boolean(inner.length) && (
<DropDown
ref={childRef}
placement="bottom"
className={groupActionsItemClassName}
title="Split Editor Right"
trigger="click"
title="More Actions..."
overlay={overlay}
>
<Icon type="split-horizontal" />
</div>
) : null}
<DropDown
ref={childRef}
placement="bottom"
className={groupActionsItemClassName}
trigger="click"
title="More Actions..."
overlay={overlay}
>
<Icon type="ellipsis" />
</DropDown>
<Icon type="ellipsis" />
</DropDown>
)}
</div>
);
}
Expand Down
11 changes: 10 additions & 1 deletion src/workbench/editor/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { getBEMElement, prefixClaName } from 'mo/common/className';
import {
getBEMElement,
getBEMModifier,
prefixClaName,
} from 'mo/common/className';

export const defaultEditorClassName = prefixClaName('editor');
export const groupClassName = getBEMElement(defaultEditorClassName, 'group');
Expand All @@ -23,6 +27,11 @@ export const groupActionsItemClassName = getBEMElement(
'group-actions-item'
);

export const groupActionItemDisabledClassName = getBEMModifier(
groupActionsItemClassName,
'disabled'
);

export const groupBreadcrumbClassName = getBEMElement(
defaultEditorClassName,
'group-breadcrumb'
Expand Down
Loading

0 comments on commit 443d4da

Please sign in to comment.