summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2024-07-09 17:59:15 +0900
committerGitHub <noreply@github.com>2024-07-09 17:59:15 +0900
commita5407131d4d15edca924e2718902cefd81e49ee2 (patch)
treebad6d1e08071e9e14624a4d64fb851f137bb4fee /packages/frontend/src/components
parentBump release actions to v2 (develop-stable(master) branches system) (#13941) (diff)
downloadmisskey-a5407131d4d15edca924e2718902cefd81e49ee2.tar.gz
misskey-a5407131d4d15edca924e2718902cefd81e49ee2.tar.bz2
misskey-a5407131d4d15edca924e2718902cefd81e49ee2.zip
fix/refactor(frontend): hotkeyの改修 (#14157)
* improve(frontend): hotkeyの改修 (#234) (cherry picked from commit 678be147f4db709dadf25d007cc2e679e98a370e) * Change path, add missing script Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com> * fix * fix * add missing keycodes * fix * update changelog --------- Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
Diffstat (limited to 'packages/frontend/src/components')
-rw-r--r--packages/frontend/src/components/MkMediaAudio.vue47
-rw-r--r--packages/frontend/src/components/MkMediaVideo.vue47
-rw-r--r--packages/frontend/src/components/MkMenu.vue20
-rw-r--r--packages/frontend/src/components/MkModal.vue8
-rw-r--r--packages/frontend/src/components/MkNote.vue57
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue26
6 files changed, 148 insertions, 57 deletions
diff --git a/packages/frontend/src/components/MkMediaAudio.vue b/packages/frontend/src/components/MkMediaAudio.vue
index ebd4fc9ca4..e8dfcc7768 100644
--- a/packages/frontend/src/components/MkMediaAudio.vue
+++ b/packages/frontend/src/components/MkMediaAudio.vue
@@ -80,6 +80,7 @@ import type { MenuItem } from '@/types/menu.js';
import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
+import { type Keymap } from '@/scripts/hotkey.js';
import bytes from '@/filters/bytes.js';
import { hms } from '@/filters/hms.js';
import MkMediaRange from '@/components/MkMediaRange.vue';
@@ -90,32 +91,44 @@ const props = defineProps<{
}>();
const keymap = {
- 'up': () => {
- if (hasFocus() && audioEl.value) {
- volume.value = Math.min(volume.value + 0.1, 1);
- }
+ 'up': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && audioEl.value) {
+ volume.value = Math.min(volume.value + 0.1, 1);
+ }
+ },
},
- 'down': () => {
- if (hasFocus() && audioEl.value) {
- volume.value = Math.max(volume.value - 0.1, 0);
- }
+ 'down': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && audioEl.value) {
+ volume.value = Math.max(volume.value - 0.1, 0);
+ }
+ },
},
- 'left': () => {
- if (hasFocus() && audioEl.value) {
- audioEl.value.currentTime = Math.max(audioEl.value.currentTime - 5, 0);
- }
+ 'left': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && audioEl.value) {
+ audioEl.value.currentTime = Math.max(audioEl.value.currentTime - 5, 0);
+ }
+ },
},
- 'right': () => {
- if (hasFocus() && audioEl.value) {
- audioEl.value.currentTime = Math.min(audioEl.value.currentTime + 5, audioEl.value.duration);
- }
+ 'right': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && audioEl.value) {
+ audioEl.value.currentTime = Math.min(audioEl.value.currentTime + 5, audioEl.value.duration);
+ }
+ },
},
'space': () => {
if (hasFocus()) {
togglePlayPause();
}
},
-};
+} as const satisfies Keymap;
// PlayerElもしくはその子要素にフォーカスがあるかどうか
function hasFocus() {
diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index 707d7c1501..7c46084c63 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -112,6 +112,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { ref, shallowRef, computed, watch, onDeactivated, onActivated, onMounted } from 'vue';
import * as Misskey from 'misskey-js';
import type { MenuItem } from '@/types/menu.js';
+import { type Keymap } from '@/scripts/hotkey.js';
import bytes from '@/filters/bytes.js';
import { hms } from '@/filters/hms.js';
import { defaultStore } from '@/store.js';
@@ -127,32 +128,44 @@ const props = defineProps<{
}>();
const keymap = {
- 'up': () => {
- if (hasFocus() && videoEl.value) {
- volume.value = Math.min(volume.value + 0.1, 1);
- }
+ 'up': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && videoEl.value) {
+ volume.value = Math.min(volume.value + 0.1, 1);
+ }
+ },
},
- 'down': () => {
- if (hasFocus() && videoEl.value) {
- volume.value = Math.max(volume.value - 0.1, 0);
- }
+ 'down': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && videoEl.value) {
+ volume.value = Math.max(volume.value - 0.1, 0);
+ }
+ },
},
- 'left': () => {
- if (hasFocus() && videoEl.value) {
- videoEl.value.currentTime = Math.max(videoEl.value.currentTime - 5, 0);
- }
+ 'left': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && videoEl.value) {
+ videoEl.value.currentTime = Math.max(videoEl.value.currentTime - 5, 0);
+ }
+ },
},
- 'right': () => {
- if (hasFocus() && videoEl.value) {
- videoEl.value.currentTime = Math.min(videoEl.value.currentTime + 5, videoEl.value.duration);
- }
+ 'right': {
+ allowRepeat: true,
+ callback: () => {
+ if (hasFocus() && videoEl.value) {
+ videoEl.value.currentTime = Math.min(videoEl.value.currentTime + 5, videoEl.value.duration);
+ }
+ },
},
'space': () => {
if (hasFocus()) {
togglePlayPause();
}
},
-};
+} as const satisfies Keymap;
// PlayerElもしくはその子要素にフォーカスがあるかどうか
function hasFocus() {
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index d91239b9e2..119504f744 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -98,6 +98,7 @@ import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuRadio
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { isTouchUsing } from '@/scripts/touch.js';
+import { type Keymap } from '@/scripts/hotkey.js';
const childrenCache = new WeakMap<MenuParent, MenuItem[]>();
</script>
@@ -125,11 +126,20 @@ const items2 = ref<InnerMenuItem[]>();
const child = shallowRef<InstanceType<typeof XChild>>();
-const keymap = computed(() => ({
- 'up|k|shift+tab': focusUp,
- 'down|j|tab': focusDown,
- 'esc': close,
-}));
+const keymap = {
+ 'up|k|shift+tab': {
+ allowRepeat: true,
+ callback: () => focusUp(),
+ },
+ 'down|j|tab': {
+ allowRepeat: true,
+ callback: () => focusDown(),
+ },
+ 'esc': {
+ allowRepeat: true,
+ callback: () => close(false),
+ },
+} as const satisfies Keymap;
const childShowingItem = ref<MenuItem | null>();
diff --git a/packages/frontend/src/components/MkModal.vue b/packages/frontend/src/components/MkModal.vue
index 9e69ab2207..264d8b6c9c 100644
--- a/packages/frontend/src/components/MkModal.vue
+++ b/packages/frontend/src/components/MkModal.vue
@@ -47,6 +47,7 @@ import * as os from '@/os.js';
import { isTouchUsing } from '@/scripts/touch.js';
import { defaultStore } from '@/store.js';
import { deviceKind } from '@/scripts/device-kind.js';
+import { type Keymap } from '@/scripts/hotkey.js';
function getFixedContainer(el: Element | null): Element | null {
if (el == null || el.tagName === 'BODY') return null;
@@ -154,8 +155,11 @@ if (type.value === 'drawer') {
}
const keymap = {
- 'esc': () => emit('esc'),
-};
+ 'esc': {
+ allowRepeat: true,
+ callback: () => emit('esc'),
+ },
+} as const satisfies Keymap;
const MARGIN = 16;
const SCROLLBAR_THICKNESS = 16;
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 1313e4c58e..5f1820a379 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -198,6 +198,7 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
import { shouldCollapsed } from '@/scripts/collapsed.js';
import { isEnabledUrlPreview } from '@/instance.js';
+import { type Keymap } from '@/scripts/hotkey.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -294,15 +295,53 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
}
const keymap = {
- 'r': () => reply(true),
- 'e|a|plus': () => react(true),
- 'q': () => renote(true),
- 'up|k|shift+tab': focusBefore,
- 'down|j|tab': focusAfter,
- 'esc': blur,
- 'm|o': () => showMenu(true),
- 's': () => showContent.value !== showContent.value,
-};
+ 'r': () => {
+ if (renoteCollapsed.value) return;
+ reply();
+ },
+ 'e|a|plus': () => {
+ if (renoteCollapsed.value) return;
+ react();
+ },
+ 'q': () => {
+ if (renoteCollapsed.value) return;
+ renote();
+ },
+ 'm': () => {
+ if (renoteCollapsed.value) return;
+ showMenu();
+ },
+ 'c': () => {
+ if (renoteCollapsed.value) return;
+ if (!defaultStore.state.showClipButtonInNoteFooter) return;
+ clip();
+ },
+ 'o': () => {
+ if (renoteCollapsed.value) return;
+ galleryEl.value?.openGallery();
+ },
+ 'v|enter': () => {
+ if (renoteCollapsed.value) {
+ renoteCollapsed.value = false;
+ } else if (appearNote.value.cw != null) {
+ showContent.value = !showContent.value;
+ } else if (isLong) {
+ collapsed.value = !collapsed.value;
+ }
+ },
+ 'esc': {
+ allowRepeat: true,
+ callback: () => blur(),
+ },
+ 'up|k|shift+tab': {
+ allowRepeat: true,
+ callback: () => focusBefore(),
+ },
+ 'down|j|tab': {
+ allowRepeat: true,
+ callback: () => focusAfter(),
+ },
+} as const satisfies Keymap;
provide('react', (reaction: string) => {
misskeyApi('notes/reactions/create', {
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index bc1f416373..8f65e3b60a 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -233,6 +233,7 @@ import MkPagination, { type Paging } from '@/components/MkPagination.vue';
import MkReactionIcon from '@/components/MkReactionIcon.vue';
import MkButton from '@/components/MkButton.vue';
import { isEnabledUrlPreview } from '@/instance.js';
+import { type Keymap } from '@/scripts/hotkey.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -294,13 +295,24 @@ const replies = ref<Misskey.entities.Note[]>([]);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || appearNote.value.userId === $i?.id);
const keymap = {
- 'r': () => reply(true),
- 'e|a|plus': () => react(true),
- 'q': () => renote(true),
- 'esc': blur,
- 'm|o': () => showMenu(true),
- 's': () => showContent.value !== showContent.value,
-};
+ 'r': () => reply(),
+ 'e|a|plus': () => react(),
+ 'q': () => renote(),
+ 'm': () => showMenu(),
+ 'c': () => {
+ if (!defaultStore.state.showClipButtonInNoteFooter) return;
+ clip();
+ },
+ 'v|enter': () => {
+ if (appearNote.value.cw != null) {
+ showContent.value = !showContent.value;
+ }
+ },
+ 'esc': {
+ allowRepeat: true,
+ callback: () => blur(),
+ },
+} as const satisfies Keymap;
provide('react', (reaction: string) => {
misskeyApi('notes/reactions/create', {