Skip to content

Commit

Permalink
Change: ショートカットキー周りをHotkeyManagerにまとめる (VOICEVOX#1822)
Browse files Browse the repository at this point in the history
* Add: HotkeyManagerを追加

* Add: とりあえずUndo/Redoは動いた

* Change: Pluginに

* Change: hotkey-jsに

* Change: hotkeyManagerに置き換え

* Change: デフォルトパラメータに

* Code: ドキュメントを追加

* Add: sing側に同じ名前でショートカットを登録できるように

* Revert: Spaceキー再生のコードを削除

* Improve: 可読性を改善

* Delete: keepDefaultBehaviorを削除

* Change: scopeを使うように

* Code: 「ショートカットキーの処理」を使うように

* Fix: 同じキーバインドが登録されてると片方が動かなくなるのを修正

* Code: 可読性を向上

* Code: 変数名周りを改修

* Change: HotkeyAction -> HotkeyActionName

* Change: ActionKey -> ActionId

* Change: action ->name

* Change: window.electron.logInfoをを使うようにする

* Code: 変数名を変更

* Change: undefined | HotkeySetting[]にする

Co-Authored-By: Hiroshiba <[email protected]>

* Add: テストを追加

* Refactor: refreshBindingsを分解

* Change: hotkeys.filterを一番上に持ってくる

Co-Authored-By: Hiroshiba <[email protected]>

* Change: getSettingでthrowするようにする

Co-Authored-By: Hiroshiba <[email protected]>

* Delete: eslintのignoreを使わないコードにする

Co-Authored-By: Hiroshiba <[email protected]>

* Code: コメントを追加

Co-Authored-By: Hiroshiba <[email protected]>

* Change: as unknown asをなくす

Co-Authored-By: Hiroshiba <[email protected]>

* Fix: 割り当て -> 未割り当て -> 割り当ての挙動を修正

Co-Authored-By: Hiroshiba <[email protected]>

* Change: logをDIする

* Code: コメントを追加

* Change: 条件を変更

* 下に移動

* to combination

* Fix: 良い感じにクリーンアップするように

* Fix: テストを修正

* Improve: 良い感じに

Co-Authored-By: Hiroshiba <[email protected]>

* Improve: エラーメッセージを改善

Co-Authored-By: Hiroshiba <[email protected]>

* Change: IDを使わないように

* Refactor: isSameHotkeyTarget/isNotSameHotkeyTargetを追加

* Delete: unbindUnregisteredCombinationsを削除

* unbindedCombinationsを下に

* doc集約

* プライベート変数の説明追加

* Code: コメントをdoc commentに

* Change: beforeEachで登録するのをやめる

---------

Co-authored-by: Hiroshiba <[email protected]>
Co-authored-by: Hiroshiba <[email protected]>
  • Loading branch information
3 people authored Feb 21, 2024
1 parent ad6f682 commit 3869583
Show file tree
Hide file tree
Showing 17 changed files with 741 additions and 368 deletions.
40 changes: 14 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"electron-window-state": "5.0.3",
"encoding-japanese": "1.0.30",
"glob": "8.0.3",
"hotkeys-js": "3.13.6",
"immer": "9.0.21",
"markdown-it": "13.0.2",
"move-file": "3.0.0",
Expand Down Expand Up @@ -80,7 +81,6 @@
"@types/encoding-japanese": "1.0.18",
"@types/glob": "8.0.0",
"@types/markdown-it": "12.2.0",
"@types/mousetrap": "1.6.8",
"@types/multistream": "4.1.0",
"@types/semver": "7.3.9",
"@types/unzipper": "0.10.5",
Expand Down Expand Up @@ -110,7 +110,6 @@
"license-checker": "25.0.1",
"markdownlint": "0.31.1",
"markdownlint-cli": "0.37.0",
"mousetrap": "1.6.5",
"node-fetch": "3.3.1",
"optionator": "0.9.1",
"prettier": "2.3.0",
Expand Down
55 changes: 23 additions & 32 deletions src/components/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
</template>

<script setup lang="ts">
import { watch, onMounted, ref, computed } from "vue";
import { watch, onMounted, ref, computed, toRaw } from "vue";
import { useGtm } from "@gtm-support/vue-gtm";
import { useRoute } from "vue-router";
import Mousetrap from "mousetrap";
import { EngineId } from "@/type/preload";
import ErrorBoundary from "@/components/ErrorBoundary.vue";
import { useStore } from "@/store";
import { isOnCommandOrCtrlKeyDown } from "@/store/utility";
import { useHotkeyManager } from "@/plugins/hotkeyPlugin";
const store = useStore();
const route = useRoute();
Expand All @@ -48,40 +47,32 @@ watch(
{ immediate: true }
);
// エディタの切り替えを監視する
watch(
() => route.path,
async (unknownPath) => {
let path: "talk" | "song";
if (["/talk", "/song"].includes(unknownPath)) {
path = unknownPath.slice(1) as "talk" | "song";
} else {
// 不明なパスの場合はトークエディタにする
path = "talk";
window.electron.logWarn(`unknown path: ${unknownPath}`);
}
hotkeyManager.onEditorChange(path);
}
);
// ソフトウェアを初期化
const { hotkeyManager } = useHotkeyManager();
const isEnginesReady = ref(false);
onMounted(async () => {
await store.dispatch("INIT_VUEX");
// Electronのデフォルトのundo/redoを無効化
const disableDefaultUndoRedo = (event: KeyboardEvent) => {
// ctrl+z, ctrl+shift+z, ctrl+y
if (
isOnCommandOrCtrlKeyDown(event) &&
(event.key == "z" || (!event.shiftKey && event.key == "y"))
) {
event.preventDefault();
}
};
document.addEventListener("keydown", disableDefaultUndoRedo);
// ショートカットキー操作を止める条件の設定
// 止めるなら`true`を返す
Mousetrap.prototype.stopCallback = (
e: Mousetrap.ExtendedKeyboardEvent, // 未使用
element: Element,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
combo: string // 未使用
) => {
return (
element.tagName === "INPUT" ||
element.tagName === "SELECT" ||
element.tagName === "TEXTAREA" ||
(element instanceof HTMLElement && element.contentEditable === "true") ||
// メニュー項目ではショートカットキーを無効化
element.classList.contains("q-item")
);
};
const hotkeySettings = store.state.hotkeySettings;
hotkeyManager.load(structuredClone(toRaw(hotkeySettings)));
// エンジンの初期化開始
Expand Down
13 changes: 9 additions & 4 deletions src/components/Dialog/HotkeySettingDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { useStore } from "@/store";
import { parseCombo } from "@/store/setting";
import { HotkeyActionType, HotkeySettingType } from "@/type/preload";
import { HotkeyActionNameType, HotkeySettingType } from "@/type/preload";
import { useHotkeyManager, eventToCombination } from "@/plugins/hotkeyPlugin";
const props =
defineProps<{
Expand Down Expand Up @@ -271,16 +271,21 @@ const recordCombination = (event: KeyboardEvent) => {
if (!isHotkeyDialogOpened.value) {
return;
} else {
const recordedCombo = parseCombo(event);
const recordedCombo = eventToCombination(event);
lastRecord.value = recordedCombo;
event.preventDefault();
}
};
const { hotkeyManager } = useHotkeyManager();
const changeHotkeySettings = (action: string, combo: string) => {
hotkeyManager.replace({
action: action as HotkeyActionNameType,
combination: combo,
});
return store.dispatch("SET_HOTKEY_SETTINGS", {
data: {
action: action as HotkeyActionType,
action: action as HotkeyActionNameType,
combination: combo,
},
});
Expand Down
34 changes: 24 additions & 10 deletions src/components/Menu/MenuBar/BaseMenuBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@ import TitleBarButtons from "./TitleBarButtons.vue";
import TitleBarEditorSwitcher from "./TitleBarEditorSwitcher.vue";
import { useStore } from "@/store";
import { base64ImageToUri } from "@/helpers/imageHelper";
import { HotkeyActionType, HotkeyReturnType } from "@/type/preload";
import { setHotkeyFunctions } from "@/store/setting";
import { useHotkeyManager } from "@/plugins/hotkeyPlugin";
const props =
defineProps<{
/** 「ファイル」メニューのサブメニュー */
fileSubMenuData: MenuItemData[];
/** エディタの種類 */
editor: "talk" | "song";
}>();
const store = useStore();
const { registerHotkeyWithCleanup } = useHotkeyManager();
const currentVersion = ref("");
// デフォルトエンジンの代替先ポート
Expand Down Expand Up @@ -439,14 +441,26 @@ watch(uiLocked, () => {
}
});
const hotkeyMap = new Map<HotkeyActionType, () => HotkeyReturnType>([
["新規プロジェクト", createNewProject],
["プロジェクトを上書き保存", saveProject],
["プロジェクトを名前を付けて保存", saveProjectAs],
["プロジェクト読み込み", importProject],
]);
setHotkeyFunctions(hotkeyMap);
registerHotkeyWithCleanup({
editor: props.editor,
callback: createNewProject,
name: "新規プロジェクト",
});
registerHotkeyWithCleanup({
editor: props.editor,
callback: saveProject,
name: "プロジェクトを上書き保存",
});
registerHotkeyWithCleanup({
editor: props.editor,
callback: saveProjectAs,
name: "プロジェクトを名前を付けて保存",
});
registerHotkeyWithCleanup({
editor: props.editor,
callback: importProject,
name: "プロジェクト読み込み",
});
</script>

<style lang="scss">
Expand Down
4 changes: 2 additions & 2 deletions src/components/Menu/MenuItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
import { ref, computed, watch } from "vue";
import { MenuItemData } from "./type";
import { useStore } from "@/store";
import { hotkeyActionSchema } from "@/type/preload";
import { hotkeyActionNameSchema } from "@/type/preload";
const props = withDefaults(
defineProps<{
selected?: boolean;
Expand All @@ -96,7 +96,7 @@ const hotkeySettingsMap = computed(
)
);
const getMenuBarHotkey = (rawLabel: string) => {
const label = hotkeyActionSchema.safeParse(rawLabel);
const label = hotkeyActionNameSchema.safeParse(rawLabel);
if (!label.success) {
return "";
}
Expand Down
13 changes: 2 additions & 11 deletions src/components/Sing/MenuBar.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
<template>
<base-menu-bar :file-sub-menu-data="fileSubMenuData" />
<base-menu-bar editor="song" :file-sub-menu-data="fileSubMenuData" />
</template>

<script setup lang="ts">
import { computed } from "vue";
import { MenuItemData } from "@/components/Menu/type";
import { useStore } from "@/store";
import { HotkeyActionType, HotkeyReturnType } from "@/type/preload";
import { setHotkeyFunctions } from "@/store/setting";
import BaseMenuBar from "@/components/Menu/MenuBar/BaseMenuBar.vue";
import { MenuItemData } from "@/components/Menu/type";
const store = useStore();
const uiLocked = computed(() => store.getters.UI_LOCKED);
Expand Down Expand Up @@ -55,11 +53,4 @@ const fileSubMenuData: MenuItemData[] = [
disableWhenUiLocked: true,
},
];
const hotkeyMap = new Map<HotkeyActionType, () => HotkeyReturnType>([
// NOTE: 初期設定なし
// ["新規", createNewSingProject],
]);
setHotkeyFunctions(hotkeyMap);
</script>
14 changes: 14 additions & 0 deletions src/components/Sing/ToolBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,22 @@ import {
isValidVoiceKeyShift,
} from "@/sing/domain";
import CharacterMenuButton from "@/components/Sing/CharacterMenuButton/MenuButton.vue";
import { useHotkeyManager } from "@/plugins/hotkeyPlugin";
const store = useStore();
const { registerHotkeyWithCleanup } = useHotkeyManager();
registerHotkeyWithCleanup({
editor: "song",
name: "再生/停止",
callback: () => {
if (nowPlaying.value) {
stop();
} else {
play();
}
},
});
const editor = "song";
const canUndo = computed(() => store.getters.CAN_UNDO(editor));
Expand Down
Loading

0 comments on commit 3869583

Please sign in to comment.