Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change: ショートカットキー周りをHotkeyManagerにまとめる #1822

Merged
merged 52 commits into from
Feb 21, 2024
Merged
Changes from 3 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
9d55fb9
Add: HotkeyManagerを追加
sevenc-nanashi Feb 3, 2024
421903b
Add: とりあえずUndo/Redoは動いた
sevenc-nanashi Feb 3, 2024
22c572c
Change: Pluginに
sevenc-nanashi Feb 3, 2024
a83f4a3
Change: hotkey-jsに
sevenc-nanashi Feb 3, 2024
cd5469c
Change: hotkeyManagerに置き換え
sevenc-nanashi Feb 3, 2024
f5fe090
Change: デフォルトパラメータに
sevenc-nanashi Feb 3, 2024
b93a07c
Code: ドキュメントを追加
sevenc-nanashi Feb 3, 2024
60c7336
Add: sing側に同じ名前でショートカットを登録できるように
sevenc-nanashi Feb 4, 2024
35dce47
Revert: Spaceキー再生のコードを削除
sevenc-nanashi Feb 4, 2024
5e9d70e
Improve: 可読性を改善
sevenc-nanashi Feb 6, 2024
171d8d2
Delete: keepDefaultBehaviorを削除
sevenc-nanashi Feb 6, 2024
cf5c441
Change: scopeを使うように
sevenc-nanashi Feb 6, 2024
ccc6b62
Code: 「ショートカットキーの処理」を使うように
sevenc-nanashi Feb 6, 2024
933cc43
Merge: main -> refactor/hotkey
sevenc-nanashi Feb 6, 2024
e18c353
Fix: 同じキーバインドが登録されてると片方が動かなくなるのを修正
sevenc-nanashi Feb 8, 2024
693f738
Code: 可読性を向上
sevenc-nanashi Feb 10, 2024
735a6c7
Merge: main -> refactor/hotkey
sevenc-nanashi Feb 10, 2024
a226127
Code: 変数名周りを改修
sevenc-nanashi Feb 10, 2024
14c62cf
Change: HotkeyAction -> HotkeyActionName
sevenc-nanashi Feb 10, 2024
796405a
Change: ActionKey -> ActionId
sevenc-nanashi Feb 10, 2024
bd74cfc
Change: action ->name
sevenc-nanashi Feb 10, 2024
473a780
Change: window.electron.logInfoをを使うようにする
sevenc-nanashi Feb 10, 2024
84729c8
Code: 変数名を変更
sevenc-nanashi Feb 10, 2024
3881365
Change: undefined | HotkeySetting[]にする
sevenc-nanashi Feb 10, 2024
2a0b170
Add: テストを追加
sevenc-nanashi Feb 10, 2024
c3fac82
Refactor: refreshBindingsを分解
sevenc-nanashi Feb 10, 2024
299dc1c
Change: hotkeys.filterを一番上に持ってくる
sevenc-nanashi Feb 11, 2024
45d1992
Change: getSettingでthrowするようにする
sevenc-nanashi Feb 11, 2024
44f2bb7
Delete: eslintのignoreを使わないコードにする
sevenc-nanashi Feb 11, 2024
10f474f
Code: コメントを追加
sevenc-nanashi Feb 11, 2024
1571003
Change: as unknown asをなくす
sevenc-nanashi Feb 11, 2024
5e3c03f
Fix: 割り当て -> 未割り当て -> 割り当ての挙動を修正
sevenc-nanashi Feb 11, 2024
035eb23
Change: logをDIする
sevenc-nanashi Feb 11, 2024
c68fc07
Merge: main -> refactor/hotkey
sevenc-nanashi Feb 11, 2024
1ae9b38
Code: コメントを追加
sevenc-nanashi Feb 11, 2024
1452b82
Change: 条件を変更
sevenc-nanashi Feb 14, 2024
5c63293
下に移動
Hiroshiba Feb 14, 2024
7a5e6f8
Merge remote-tracking branch 'upstream/main' into pr/sevenc-nanashi/1…
Hiroshiba Feb 14, 2024
96ed5d7
to combination
Hiroshiba Feb 14, 2024
ed32545
Fix: 良い感じにクリーンアップするように
sevenc-nanashi Feb 15, 2024
5475247
Fix: テストを修正
sevenc-nanashi Feb 15, 2024
925fd13
Improve: 良い感じに
sevenc-nanashi Feb 16, 2024
017d69e
Improve: エラーメッセージを改善
sevenc-nanashi Feb 16, 2024
c90ae78
Change: IDを使わないように
sevenc-nanashi Feb 18, 2024
e81b28a
Refactor: isSameHotkeyTarget/isNotSameHotkeyTargetを追加
sevenc-nanashi Feb 18, 2024
81afdfc
Delete: unbindUnregisteredCombinationsを削除
sevenc-nanashi Feb 18, 2024
22e0236
Merge: main -> refactor/hotkey
sevenc-nanashi Feb 19, 2024
02ebfdd
unbindedCombinationsを下に
Hiroshiba Feb 20, 2024
7fefe74
doc集約
Hiroshiba Feb 20, 2024
92551fe
プライベート変数の説明追加
Hiroshiba Feb 20, 2024
116a796
Code: コメントをdoc commentに
sevenc-nanashi Feb 20, 2024
ea7a853
Change: beforeEachで登録するのをやめる
sevenc-nanashi Feb 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 56 additions & 51 deletions src/plugins/hotkeyPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,21 @@ export const useHotkeyManager = () => {
return { hotkeyManager, registerHotkeyWithCleanup };
};

type Editor = "talk" | "song";

/**
* ショートカットキーの処理を登録するための型。
*/
export type HotkeyAction = {
/** どちらのエディタで有効か */
editor: "talk" | "song";
editor: Editor;
/** テキストボックス内で有効か。デフォルトはfalse。 */
enableInTextbox?: boolean;
/** 名前。 */
name: HotkeyActionNameType;
/** ショートカットキーが押されたときの処理。 */
callback: (e: KeyboardEvent) => void;
};
type HotkeyActionId = `${"talk" | "song"}:${HotkeyActionNameType}`;

const actionToId = (action: HotkeyAction): HotkeyActionId =>
`${action.editor}:${action.name}`;
const idToEditorAndName = (
id: HotkeyActionId
): [editor: "talk" | "song", name: HotkeyActionNameType] =>
id.split(":", 2) as [editor: "talk" | "song", name: HotkeyActionNameType];

export type HotkeysJs = {
(
Expand All @@ -73,14 +67,31 @@ hotkeys.filter = () => {
};
type Log = (message: string, ...args: unknown[]) => void;

type RegisteredCombination = {
editor: Editor;
name: HotkeyActionNameType;
combination: string;
};

interface HotkeyTarget {
name: HotkeyActionNameType;
editor: Editor;
}
const isSameHotkeyTarget = (a: HotkeyTarget) => (b: HotkeyTarget) => {
return a.name === b.name && a.editor === b.editor;
};
const isNotSameHotkeyTarget = (a: HotkeyTarget) => (b: HotkeyTarget) => {
return a.name !== b.name || a.editor !== b.editor;
};

/**
* ショートカットキーの管理を行うクラス。
*/
export class HotkeyManager {
private actions: HotkeyAction[] = [];
private settings: HotkeySettingType[] | undefined;
// 登録されているショートカットキーの組み合わせ。キーは「エディタ:アクション」で、値はcombination。
private registeredCombinations: Partial<Record<HotkeyActionId, string>> = {};
// 登録されているショートカットキーの組み合わせ。
private registeredCombinations: RegisteredCombination[] = [];

private hotkeys: HotkeysJs;
private log: Log;
Expand Down Expand Up @@ -114,26 +125,35 @@ export class HotkeyManager {
return setting;
}

private getRegisteredCombination(action: HotkeyAction): string | undefined {
return this.registeredCombinations.find(isSameHotkeyTarget(action))
?.combination;
}

private refreshBinding(): void {
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved
if (!this.settings) {
return;
}

this.unbindUnregisteredActions();

const unregisteredCombinations = this.registeredCombinations.filter(
(c) => !this.actions.some(isSameHotkeyTarget(c))
);
const changedActions = this.actions.filter((a) => {
const setting = this.getSetting(a);
return this.registeredCombinations[actionToId(a)] !== setting.combination;
return this.getRegisteredCombination(a) !== setting.combination;
});
if (changedActions.length === 0) {
if (changedActions.length === 0 && unregisteredCombinations.length === 0) {
return;
}
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved

const actionsToUnbind = changedActions.filter((a) => {
// 未登録のものを弾く
return this.registeredCombinations[actionToId(a)] != undefined;
const unbindedCombinations = changedActions.flatMap((a) => {
const combination = this.registeredCombinations.find(
isSameHotkeyTarget(a)
);
// 空じゃないCombinationを探す
return combination?.combination ? [combination] : [];
});
this.unbindActions(actionsToUnbind);
this.unbindActions([...unbindedCombinations, ...unregisteredCombinations]);

const actionsToBind = changedActions.filter((a) => {
const setting = this.getSetting(a);
Expand All @@ -143,34 +163,14 @@ export class HotkeyManager {
this.bindActions(actionsToBind);
}

private unbindUnregisteredActions(): void {
for (const [id, combination] of Object.entries(
this.registeredCombinations
)) {
if (!combination) {
continue;
}
if (this.actions.some((a) => actionToId(a) === id)) {
continue;
}
const [editor, name] = idToEditorAndName(id as HotkeyActionId);

this.log(`Unbind: ${name}(${combination}) in ${editor}`);
this.hotkeys.unbind(combinationToBindingKey(combination), editor);
this.registeredCombinations[id as HotkeyActionId] = undefined;
}
}

private unbindActions(actions: HotkeyAction[]): void {
for (const action of actions) {
const combination = this.registeredCombinations[actionToId(action)];
if (!combination) {
throw new Error("assert: combination != undefined");
}
const bindingKey = combinationToBindingKey(combination);
this.log("Unbind:", bindingKey, "in", action.editor);
this.hotkeys.unbind(bindingKey, action.editor);
this.registeredCombinations[actionToId(action)] = undefined;
private unbindActions(combinations: RegisteredCombination[]): void {
for (const combination of combinations) {
const bindingKey = combinationToBindingKey(combination.combination);
this.log("Unbind:", bindingKey, "in", combination.editor);
this.hotkeys.unbind(bindingKey, combination.editor);
this.registeredCombinations = this.registeredCombinations.filter(
isNotSameHotkeyTarget(combination)
);
}
}

Expand Down Expand Up @@ -212,7 +212,14 @@ export class HotkeyManager {
action.callback(e);
}
);
this.registeredCombinations[actionToId(action)] = setting.combination;
this.registeredCombinations = this.registeredCombinations.filter(
isNotSameHotkeyTarget(action)
);
this.registeredCombinations.push({
editor: action.editor,
name: action.name,
combination: setting.combination,
});
}
}

Expand Down Expand Up @@ -248,9 +255,7 @@ export class HotkeyManager {
* ショートカットキーの処理の登録を解除する。
*/
unregister(data: HotkeyAction): void {
this.actions = this.actions.filter(
(a) => a.name !== data.name || a.editor !== data.editor
);
this.actions = this.actions.filter(isNotSameHotkeyTarget(data));
this.refreshBinding();
}

Expand Down