@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 8.75 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as Host from"../../core/host/host.js";import*as Platform from"../../core/platform/platform.js";import*as Root from"../../core/root/root.js";import{getRegisteredActionExtensions}from"./ActionRegistration.js";import{Context}from"./Context.js";import{Dialog}from"./Dialog.js";import{KeyboardShortcut,Modifiers,Type}from"./KeyboardShortcut.js";import{isEditing}from"./UIUtils.js";let shortcutRegistryInstance;export class ShortcutRegistry{actionRegistry;actionToShortcut;keyMap;activePrefixKey;activePrefixTimeout;consumePrefix;devToolsDefaultShortcutActions;disabledDefaultShortcutsForAction;keybindSetSetting;userShortcutsSetting;constructor(t){this.actionRegistry=t,this.actionToShortcut=new Platform.MapUtilities.Multimap,this.keyMap=new ShortcutTreeNode(0,0),this.activePrefixKey=null,this.activePrefixTimeout=null,this.consumePrefix=null,this.devToolsDefaultShortcutActions=new Set,this.disabledDefaultShortcutsForAction=new Platform.MapUtilities.Multimap,this.keybindSetSetting=Common.Settings.Settings.instance().moduleSetting("activeKeybindSet"),this.keybindSetSetting.addChangeListener((t=>{Host.userMetrics.keybindSetSettingChanged(t.data),this.registerBindings()})),this.userShortcutsSetting=Common.Settings.Settings.instance().moduleSetting("userShortcuts"),this.userShortcutsSetting.addChangeListener(this.registerBindings,this),this.registerBindings()}static instance(t={forceNew:null,actionRegistry:null}){const{forceNew:e,actionRegistry:o}=t;if(!shortcutRegistryInstance||e){if(!o)throw new Error("Missing actionRegistry for shortcutRegistry");shortcutRegistryInstance=new ShortcutRegistry(o)}return shortcutRegistryInstance}static removeInstance(){shortcutRegistryInstance=void 0}applicableActions(t,e={}){let o=[];const i=(this.activePrefixKey||this.keyMap).getNode(t);i&&(o=i.actions());const r=this.actionRegistry.applicableActions(o,Context.instance());if(i)for(const t of Object.keys(e))if(i.actions().indexOf(t)>=0){const e=this.actionRegistry.action(t);e&&r.push(e)}return r}shortcutsForAction(t){return[...this.actionToShortcut.get(t)]}actionsForDescriptors(t){let e=this.keyMap;for(const{key:o}of t){if(!e)return[];e=e.getNode(o)}return e?e.actions():[]}globalShortcutKeys(){const t=[];for(const e of this.keyMap.chords().values()){const o=e.actions();(this.actionRegistry.applicableActions(o,Context.instance()).length||e.hasChords())&&t.push(e.key())}return t}keysForActions(t){const e=t.flatMap((t=>[...this.actionToShortcut.get(t)].flatMap((t=>t.descriptors.map((t=>t.key))))));return[...new Set(e)]}shortcutTitleForAction(t){for(const e of this.actionToShortcut.get(t))return e.title()}handleShortcut(t,e){this.handleKey(KeyboardShortcut.makeKeyFromEvent(t),t.key,t,e)}actionHasDefaultShortcut(t){return this.devToolsDefaultShortcutActions.has(t)}getShortcutListener(t){const e=Object.keys(t).flatMap((t=>[...this.actionToShortcut.get(t)])),o=new ShortcutTreeNode(0,0);return e.forEach((t=>{o.addKeyMapping(t.descriptors.map((t=>t.key)),t.action)})),e=>{const i=KeyboardShortcut.makeKeyFromEvent(e),r=this.activePrefixKey?o.getNode(this.activePrefixKey.key()):o;r&&r.getNode(i)&&this.handleShortcut(e,t)}}addShortcutListener(t,e){const o=this.getShortcutListener(e);return t.addEventListener("keydown",o),o}async handleKey(t,e,o,i){const r=t>>8,s=Boolean(i)||Boolean(this.activePrefixKey),n=this.keyMap.getNode(t),c=this.applicableActions(t,i).length>0||n&&n.hasChords();if((s||!function(){if(!o||!isEditing()||/^F\d+|Control|Shift|Alt|Meta|Escape|Win|U\+001B$/.test(e))return!1;if(!r)return!0;const i=Modifiers;if(Host.Platform.isMac()){if(KeyboardShortcut.makeKey("z",i.Meta)===t)return!0;if(KeyboardShortcut.makeKey("z",i.Meta|i.Shift)===t)return!0}else{if(KeyboardShortcut.makeKey("z",i.Ctrl)===t)return!0;if(KeyboardShortcut.makeKey("y",i.Ctrl)===t)return!0;if(!Host.Platform.isWin()&&KeyboardShortcut.makeKey("z",i.Ctrl|i.Shift)===t)return!0}if((r&(i.Ctrl|i.Alt))==(i.Ctrl|i.Alt))return Host.Platform.isWin();return!a(i.Ctrl)&&!a(i.Alt)&&!a(i.Meta)}())&&c&&!KeyboardShortcut.isModifier(KeyboardShortcut.keyCodeAndModifiersFromKey(t).keyCode)&&(o&&o.consume(!0),s||!Dialog.hasInstance())){if(this.activePrefixTimeout){clearTimeout(this.activePrefixTimeout);const t=await h.call(this);if(this.activePrefixKey=null,this.activePrefixTimeout=null,t)return;this.consumePrefix&&await this.consumePrefix()}n&&n.hasChords()?(this.activePrefixKey=n,this.consumePrefix=async()=>{this.activePrefixKey=null,this.activePrefixTimeout=null,await h.call(this)},this.activePrefixTimeout=window.setTimeout(this.consumePrefix,KeyTimeout)):await h.call(this)}function a(t){return Boolean(r&t)}async function h(){const e=this.applicableActions(t,i);if(!e.length)return!1;for(const t of e){let e;if(i&&i[t.id()]&&(e=await i[t.id()]()),i||(e=await t.execute()),e)return Host.userMetrics.keyboardShortcutFired(t.id()),!0}return!1}}registerUserShortcut(t){for(const e of this.disabledDefaultShortcutsForAction.get(t.action))if(e.descriptorsMatch(t.descriptors)&&e.hasKeybindSet(this.keybindSetSetting.get()))return void this.removeShortcut(e);for(const e of this.actionToShortcut.get(t.action))if(e.descriptorsMatch(t.descriptors)&&e.hasKeybindSet(this.keybindSetSetting.get()))return;this.addShortcutToSetting(t)}removeShortcut(t){t.type===Type.DefaultShortcut||t.type===Type.KeybindSetShortcut?this.addShortcutToSetting(t.changeType(Type.DisabledDefault)):this.removeShortcutFromSetting(t)}disabledDefaultsForAction(t){return this.disabledDefaultShortcutsForAction.get(t)}addShortcutToSetting(t){const e=this.userShortcutsSetting.get();e.push(t),this.userShortcutsSetting.set(e)}removeShortcutFromSetting(t){const e=this.userShortcutsSetting.get(),o=e.findIndex(t.equals,t);-1!==o&&(e.splice(o,1),this.userShortcutsSetting.set(e))}registerShortcut(t){this.actionToShortcut.set(t.action,t),this.keyMap.addKeyMapping(t.descriptors.map((t=>t.key)),t.action)}registerBindings(){this.actionToShortcut.clear(),this.keyMap.clear();const t=this.keybindSetSetting.get();this.disabledDefaultShortcutsForAction.clear(),this.devToolsDefaultShortcutActions.clear();const e=[];if(Root.Runtime.experiments.isEnabled("keyboardShortcutEditor")){const t=this.userShortcutsSetting.get();for(const o of t){const t=KeyboardShortcut.createShortcutFromSettingObject(o);t.type===Type.DisabledDefault?this.disabledDefaultShortcutsForAction.set(t.action,t):(ForwardedActions.has(t.action)&&e.push(...t.descriptors.map((t=>KeyboardShortcut.keyCodeAndModifiersFromKey(t.key)))),this.registerShortcut(t))}}for(const t of getRegisteredActionExtensions()){const r=t.id(),s=t.bindings();for(let t=0;s&&t<s.length;++t){const n=s[t].keybindSets;if(!o(s[t].platform)||!i(n))continue;const c=s[t].shortcut.split(/\s+/).map(KeyboardShortcut.makeDescriptorFromBindingShortcut);if(c.length>0){if(this.isDisabledDefault(c,r)){this.devToolsDefaultShortcutActions.add(r);continue}ForwardedActions.has(r)&&e.push(...c.map((t=>KeyboardShortcut.keyCodeAndModifiersFromKey(t.key)))),n?(n.includes("devToolsDefault")&&this.devToolsDefaultShortcutActions.add(r),this.registerShortcut(new KeyboardShortcut(c,r,Type.KeybindSetShortcut,new Set(n)))):(this.devToolsDefaultShortcutActions.add(r),this.registerShortcut(new KeyboardShortcut(c,r,Type.DefaultShortcut)))}}}function o(t){if(!t)return!0;const e=t.split(",");let o=!1;const i=Host.Platform.platform();for(let t=0;!o&&t<e.length;++t)o=e[t]===i;return o}function i(e){return!e||e.includes(t)}Host.InspectorFrontendHost.InspectorFrontendHostInstance.setWhitelistedShortcuts(JSON.stringify(e))}isDisabledDefault(t,e){const o=this.disabledDefaultShortcutsForAction.get(e);for(const e of o)if(e.descriptorsMatch(t))return!0;return!1}}export class ShortcutTreeNode{keyInternal;actionsInternal;chordsInternal;depth;constructor(t,e=0){this.keyInternal=t,this.actionsInternal=[],this.chordsInternal=new Map,this.depth=e}addAction(t){this.actionsInternal.push(t)}key(){return this.keyInternal}chords(){return this.chordsInternal}hasChords(){return this.chordsInternal.size>0}addKeyMapping(t,e){if(!(t.length<this.depth))if(t.length===this.depth)this.addAction(e);else{const o=t[this.depth];this.chordsInternal.has(o)||this.chordsInternal.set(o,new ShortcutTreeNode(o,this.depth+1)),this.chordsInternal.get(o).addKeyMapping(t,e)}}getNode(t){return this.chordsInternal.get(t)||null}actions(){return this.actionsInternal}clear(){this.actionsInternal=[],this.chordsInternal=new Map}}export class ForwardedShortcut{static instance=new ForwardedShortcut}export const ForwardedActions=new Set(["main.toggle-dock","debugger.toggle-breakpoints-active","debugger.toggle-pause","commandMenu.show","console.show"]);export const KeyTimeout=1e3;export const DefaultShortcutSetting="devToolsDefault";