Skip to content

Commit

Permalink
Refactor: 修飾キーのcomposableを追加 (VOICEVOX#1711)
Browse files Browse the repository at this point in the history
* Refactor: 修飾キーのcomposableを追加

* Dlete: 不要なexportを削除

Co-authored-by: Hiroshiba <[email protected]>

* #1711のテスト書いてみた (#1)

---------

Co-authored-by: Hiroshiba <[email protected]>
  • Loading branch information
sevenc-nanashi and Hiroshiba authored Jan 15, 2024
1 parent 06e8721 commit e100dc9
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 37 deletions.
26 changes: 9 additions & 17 deletions src/components/AudioCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
</template>

<script setup lang="ts">
import { computed, watch, ref, nextTick, onMounted, onUnmounted } from "vue";
import { computed, watch, ref, nextTick } from "vue";
import { QInput } from "quasar";
import CharacterButton from "./CharacterButton.vue";
import { MenuItemButton, MenuItemSeparator } from "./MenuBar.vue";
Expand All @@ -119,6 +119,10 @@ import { useStore } from "@/store";
import { AudioKey, SplitTextWhenPasteType, Voice } from "@/type/preload";
import { SelectionHelperForQInput } from "@/helpers/SelectionHelperForQInput";
import { isOnCommandOrCtrlKeyDown } from "@/store/utility";
import {
useShiftKey,
useCommandOrControlKey,
} from "@/composables/useModifierKey";
const props =
defineProps<{
Expand Down Expand Up @@ -183,6 +187,10 @@ const onRootFocus = () => {
selectAndSetActiveAudioKey();
};
const isShiftKeyDown = useShiftKey();
const isCtrlOrCommandKeyDown = useCommandOrControlKey();
// 複数選択:Ctrl(Cmd)またはShiftキーが押されている時のクリック処理
const onClickWithModifierKey = (event: MouseEvent) => {
if (uiLocked.value) return;
Expand Down Expand Up @@ -241,22 +249,6 @@ const onClickWithModifierKey = (event: MouseEvent) => {
});
};
const isCtrlOrCommandKeyDown = ref(false);
const isShiftKeyDown = ref(false);
const keyEventListener = (e: KeyboardEvent) => {
isCtrlOrCommandKeyDown.value = isOnCommandOrCtrlKeyDown(e);
isShiftKeyDown.value = e.shiftKey;
};
onMounted(() => {
window.addEventListener("keydown", keyEventListener);
window.addEventListener("keyup", keyEventListener);
});
onUnmounted(() => {
window.removeEventListener("keydown", keyEventListener);
window.removeEventListener("keyup", keyEventListener);
});
const selectedVoice = computed<Voice | undefined>({
get() {
const { engineId, styleId } = audioItem.value.voice;
Expand Down
26 changes: 6 additions & 20 deletions src/components/AudioDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
"
:is-active="accentPhraseIndex === activePoint"
:selected-detail="selectedDetail"
:shift-key-flag="shiftKeyFlag"
:alt-key-flag="altKeyFlag"
:shift-key-flag="isShiftKeyDown"
:alt-key-flag="isAltKeyDown"
@click="setPlayAndStartPoint"
/>
</div>
Expand All @@ -81,7 +81,7 @@
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
import { computed, nextTick, ref, watch } from "vue";
import ToolTip from "./ToolTip.vue";
import AccentPhrase from "./AccentPhrase.vue";
import { useStore } from "@/store";
Expand All @@ -93,6 +93,7 @@ import {
} from "@/type/preload";
import { setHotkeyFunctions } from "@/store/setting";
import { EngineManifest } from "@/openapi/models";
import { useShiftKey, useAltKey } from "@/composables/useModifierKey";
const props =
defineProps<{
Expand Down Expand Up @@ -356,23 +357,8 @@ watch(nowPlaying, async (newState) => {
}
});
const shiftKeyFlag = ref(false);
const altKeyFlag = ref(false);
const keyEventListter = (event: KeyboardEvent) => {
shiftKeyFlag.value = event.shiftKey;
altKeyFlag.value = event.altKey;
};
onMounted(() => {
window.addEventListener("keyup", keyEventListter);
document.addEventListener("keydown", keyEventListter);
});
onUnmounted(() => {
window.removeEventListener("keyup", keyEventListter);
document.removeEventListener("keydown", keyEventListter);
});
const isShiftKeyDown = useShiftKey();
const isAltKeyDown = useAltKey();
</script>

<style scoped lang="scss">
Expand Down
70 changes: 70 additions & 0 deletions src/composables/useModifierKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Ref, ref, onUnmounted, onMounted, unref } from "vue";
import { isMac } from "@/type/preload";

// FIXME: Vue3.3以上では定義済みなので削除する
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyFn = (...args: any[]) => any;
type MaybeRef<T> = T | Ref<T>;
type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);
function toValue<T>(r: MaybeRefOrGetter<T>): T {
return typeof r === "function" ? (r as AnyFn)() : unref(r);
}

type Target = EventTarget & GlobalEventHandlers;

const useCreateUseKey = (
key: string,
_target: MaybeRefOrGetter<Target> = window
): Ref<boolean> => {
const target = toValue(_target);

const isActive = ref(false);

const onKeydown = (e: KeyboardEvent) => {
if (e.key === key) {
isActive.value = true;
}
};
const onKeyup = (e: KeyboardEvent) => {
if (e.key === key) {
isActive.value = false;
}
};
const onBlur = () => {
isActive.value = false;
};

onMounted(() => {
target.addEventListener("keydown", onKeydown);
target.addEventListener("keyup", onKeyup);
target.addEventListener("blur", onBlur);
});

onUnmounted(() => {
target.removeEventListener("keydown", onKeydown);
target.removeEventListener("keyup", onKeyup);
target.removeEventListener("blur", onBlur);
});

return isActive;
};

/** Shiftキーが押されているかどうかを返す */
export const useShiftKey = (target: Target = window) =>
useCreateUseKey("Shift", target);

/** Altキー(MacではOptionキー)が押されているかどうかを返す */
export const useAltKey = (target: Target = window) =>
useCreateUseKey("Alt", target);

const useMetaKey = (target: Target = window) => useCreateUseKey("Meta", target);
const useControlKey = (target: Target = window) =>
useCreateUseKey("Control", target);

/** Ctrlキー(MacではCommandキー)が押されているかどうかを返す */
export const useCommandOrControlKey = (target: Target = window) => {
if (isMac) {
return useMetaKey(target);
}
return useControlKey(target);
};
48 changes: 48 additions & 0 deletions tests/unit/composable/useModifierKey.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { mount } from "@vue/test-utils";
import { Ref } from "vue";
import {
useCommandOrControlKey,
useShiftKey,
} from "@/composables/useModifierKey";

import { isMac } from "@/type/preload";

describe("useModifierKey", () => {
// テスト用のコンポーネント
const mountWrapper = (func: (elem: HTMLElement) => Ref<boolean>) =>
mount({
setup: () => {
const elem = document.createElement("div");
return { elem, isActive: func(elem) };
},
render: () => null, // 警告防止
});

it("Shiftキーが押されている状態になる", async () => {
const wrapper = mountWrapper(useShiftKey);

// 押す
wrapper.vm.elem.dispatchEvent(
new KeyboardEvent("keydown", { key: "Shift" })
);
expect(wrapper.vm.isActive).toBe(true);

// 離す
wrapper.vm.elem.dispatchEvent(new KeyboardEvent("keyup", { key: "Shift" }));
expect(wrapper.vm.isActive).toBe(false);

// もう一度押したあとblurさせる
wrapper.vm.elem.dispatchEvent(
new KeyboardEvent("keydown", { key: "Shift" })
);
wrapper.vm.elem.dispatchEvent(new Event("blur"));
expect(wrapper.vm.isActive).toBe(false);
});

it("isMacに従ったキーが押されている状態になる", async () => {
const wrapper = mountWrapper(useCommandOrControlKey);
const key = isMac ? "Meta" : "Control";
wrapper.vm.elem.dispatchEvent(new KeyboardEvent("keydown", { key }));
expect(wrapper.vm.isActive).toBe(true);
});
});

0 comments on commit e100dc9

Please sign in to comment.