mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-27 10:32:58 +02:00
129 lines
3.4 KiB
TypeScript
129 lines
3.4 KiB
TypeScript
import CommandService from '../CommandService';
|
|
import KeymapService from '../KeymapService';
|
|
import propsHaveChanged from './propsHaveChanged';
|
|
const { createSelectorCreator, defaultMemoize } = require('reselect');
|
|
const { createCachedSelector } = require('re-reselect');
|
|
|
|
interface MenuItem {
|
|
id: string,
|
|
label: string,
|
|
click: Function,
|
|
role?: any,
|
|
accelerator?: string,
|
|
}
|
|
|
|
interface MenuItems {
|
|
[key: string]: MenuItem,
|
|
}
|
|
|
|
interface MenuItemProps {
|
|
[key:string]: any,
|
|
}
|
|
|
|
interface MenuItemPropsCache {
|
|
[key:string]: any,
|
|
}
|
|
|
|
interface MenuItemCache {
|
|
[key:string]: MenuItems,
|
|
}
|
|
|
|
const createShallowObjectEqualSelector = createSelectorCreator(
|
|
defaultMemoize,
|
|
(prev:any, next:any) => {
|
|
if (Object.keys(prev).length !== Object.keys(next).length) return false;
|
|
for (const n in prev) {
|
|
if (prev[n] !== next[n]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
);
|
|
|
|
// This selector ensures that for the given command names, the same toolbar
|
|
// button array is returned if the underlying toolbar buttons have not changed.
|
|
const selectObjectByCommands = createCachedSelector(
|
|
(state:any) => state.array,
|
|
(array:any[]) => array
|
|
)({
|
|
keySelector: (_state:any, commandNames:string[]) => {
|
|
return commandNames.join('_');
|
|
},
|
|
selectorCreator: createShallowObjectEqualSelector,
|
|
});
|
|
|
|
export default class MenuUtils {
|
|
|
|
private service_:CommandService;
|
|
private menuItemCache_:MenuItemCache = {};
|
|
private menuItemPropsCache_:MenuItemPropsCache = {};
|
|
|
|
constructor(service:CommandService) {
|
|
this.service_ = service;
|
|
}
|
|
|
|
private get service():CommandService {
|
|
return this.service_;
|
|
}
|
|
|
|
private get keymapService():KeymapService {
|
|
return KeymapService.instance();
|
|
}
|
|
|
|
private commandToMenuItem(commandName:string, onClick:Function):MenuItem {
|
|
const command = this.service.commandByName(commandName);
|
|
|
|
const item:MenuItem = {
|
|
id: command.declaration.name,
|
|
label: this.service.label(commandName),
|
|
click: () => onClick(command.declaration.name),
|
|
};
|
|
|
|
if (command.declaration.role) item.role = command.declaration.role;
|
|
|
|
if (this.keymapService && this.keymapService.acceleratorExists(commandName)) {
|
|
item.accelerator = this.keymapService.getAccelerator(commandName);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
public commandToStatefulMenuItem(commandName:string, props:any = null):MenuItem {
|
|
const output = this.commandsToMenuItems([commandName], () => {
|
|
return this.service.execute(commandName, props ? props : {});
|
|
});
|
|
return output[commandName];
|
|
}
|
|
|
|
public commandsToMenuItems(commandNames:string[], onClick:Function):MenuItems {
|
|
const key:string = `${this.keymapService.lastSaveTime}_${commandNames.join('_')}`;
|
|
if (this.menuItemCache_[key]) return this.menuItemCache_[key];
|
|
|
|
const output:MenuItems = {};
|
|
|
|
for (const commandName of commandNames) {
|
|
output[commandName] = this.commandToMenuItem(commandName, onClick);
|
|
}
|
|
|
|
this.menuItemCache_[key] = output;
|
|
|
|
return output;
|
|
}
|
|
|
|
public commandsToMenuItemProps(state:any, commandNames:string[]):MenuItemProps {
|
|
const output:MenuItemProps = {};
|
|
|
|
for (const commandName of commandNames) {
|
|
const newProps = this.service.commandMapStateToProps(commandName, state);
|
|
if (newProps === null || propsHaveChanged(this.menuItemPropsCache_[commandName], newProps)) {
|
|
output[commandName] = newProps;
|
|
this.menuItemPropsCache_[commandName] = newProps;
|
|
} else {
|
|
output[commandName] = this.menuItemPropsCache_[commandName];
|
|
}
|
|
}
|
|
|
|
return selectObjectByCommands({ array: output }, commandNames);
|
|
}
|
|
|
|
}
|