refs #3300 Enable shortcut to move focus on statuses in Home

This commit is contained in:
AkiraFukushima 2022-07-27 00:58:14 +09:00
parent 718ebdef42
commit 33c4694774
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
2 changed files with 72 additions and 16 deletions

View File

@ -17,8 +17,6 @@
:filters="filters"
v-on:update="updateToot"
v-on:delete="deleteToot"
@focusNext="focusNext"
@focusPrev="focusPrev"
@focusRight="focusSidebar"
@selectToot="focusToot(item)"
@sizeChanged="sizeChanged"
@ -39,6 +37,7 @@
<script lang="ts">
import { defineComponent, ref, computed, onMounted, onBeforeUpdate, onBeforeUnmount, watch, onUnmounted } from 'vue'
import { useMagicKeys, whenever, and } from '@vueuse/core'
import moment from 'moment'
import { ElMessage } from 'element-plus'
import { Entity } from 'megalodon'
@ -64,6 +63,7 @@ export default defineComponent({
const route = useRoute()
const i18n = useI18next()
const { reloadable } = useReloadable(store, route, i18n)
const { j, k } = useMagicKeys()
const focusedId = ref<string | null>(null)
const scrollPosition = ref<ScrollPosition | null>(null)
@ -81,19 +81,10 @@ export default defineComponent({
const scrolling = computed(() => store.state.TimelineSpace.Contents.Home.scrolling)
const openSideBar = computed(() => store.state.TimelineSpace.Contents.SideBar.openSideBar)
const startReload = computed(() => store.state.TimelineSpace.HeaderMenu.reload)
const modalOpened = computed(() => store.getters[`TimelineSpace/Modals/modalOpened`])
const modalOpened = computed<boolean>(() => store.getters[`TimelineSpace/Modals/modalOpened`])
const filters = computed(() => store.getters[`${space}/filters`])
const currentFocusedIndex = computed(() => timeline.value.findIndex(toot => focusedId.value === toot.uri + toot.id))
// const shortcutEnabled = computed(() => {
// if (modalOpened.value) {
// return false
// }
// if (!focusedId.value) {
// return true
// }
// // Sometimes toots are deleted, so perhaps focused toot don't exist.
// return currentFocusedIndex.value === -1
// })
const shortcutEnabled = computed(() => !modalOpened.value)
const filteredTimeline = computed(() => {
return timeline.value.filter(toot => {
if ('url' in toot) {
@ -167,6 +158,23 @@ export default defineComponent({
},
{ deep: true }
)
watch(focusedId, (newVal, _oldVal) => {
if (newVal && heading.value) {
store.commit(`${space}/${MUTATION_TYPES.CHANGE_HEADING}`, false)
} else if (newVal === null && !heading.value) {
store.commit(`${space}/${MUTATION_TYPES.CHANGE_HEADING}`, true)
}
})
whenever(and(j, shortcutEnabled), () => {
if (focusedId.value === null) {
focusedId.value = timeline.value[0].uri + timeline.value[0].id
} else {
focusNext()
}
})
whenever(and(k, shortcutEnabled), () => {
focusPrev()
})
const onScroll = (event: Event) => {
if (moment().diff(resizeTime.value) < 500) {

View File

@ -1,5 +1,5 @@
<template>
<div class="status" tabIndex="0" ref="status" @click="$emit('selectToot', message)" role="article" aria-label="toot">
<div class="status" tabIndex="0" ref="statusRef" @click="$emit('selectToot', message)" role="article" aria-label="toot">
<div v-if="filtered" class="filtered">Filtered</div>
<div v-if="!filtered" class="toot">
<div class="reblogger" v-if="message.reblog && !message.quote">
@ -237,7 +237,8 @@
</template>
<script lang="ts">
import { defineComponent, PropType, ref, computed, toRefs } from 'vue'
import { defineComponent, PropType, ref, computed, toRefs, watch, nextTick } from 'vue'
import { useMagicKeys, whenever, and } from '@vueuse/core'
import 'emoji-mart-vue-fast/css/emoji-mart.css'
import data from 'emoji-mart-vue-fast/data/all.json'
import moment from 'moment'
@ -311,7 +312,9 @@ export default defineComponent({
const router = useRouter()
const i18n = useI18next()
const { focused, overlaid, message, filters } = toRefs(props)
const { l, h, r, b, f, o, p, i, x } = useMagicKeys()
const statusRef = ref<any>(null)
const showContent = ref(store.state.App.ignoreCW)
const showAttachments = ref(store.state.App.ignoreNSFW)
const hideAllAttachments = ref(store.state.App.hideAllAttachments)
@ -390,6 +393,51 @@ export default defineComponent({
return QuoteSupported(sns.value, account.value.domain)
})
whenever(and(l, shortcutEnabled), () => {
ctx.emit('focusRight')
})
whenever(and(h, shortcutEnabled), () => {
ctx.emit('focusLeft')
})
whenever(and(r, shortcutEnabled), () => {
openReply()
})
whenever(and(b, shortcutEnabled), () => {
changeReblog(originalMessage.value)
})
whenever(and(f, shortcutEnabled), () => {
changeFavourite(originalMessage.value)
})
whenever(and(o, shortcutEnabled), () => {
openDetail(message.value)
})
whenever(and(p, shortcutEnabled), () => {
openUser(originalMessage.value.account)
})
whenever(and(i, shortcutEnabled), () => {
const images = mediaAttachments.value
if (images.length === 0) {
return
}
openImage(images[0].url, images)
})
whenever(and(x, shortcutEnabled), () => {
toggleSpoiler()
toggleCW()
})
watch(focused, (newVal, oldVal) => {
if (newVal) {
nextTick(() => {
statusRef.value.focus()
})
} else if (oldVal && !newVal) {
nextTick(() => {
statusRef.value.blur()
})
}
})
const username = (account: Entity.Account) => usernameWithStyle(account, displayNameStyle.value)
const accountName = (account: Entity.Account) => accountNameWithStyle(account, displayNameStyle.value)
const tootClick = (e: MouseEvent) => {
@ -628,6 +676,7 @@ export default defineComponent({
}
return {
statusRef,
emojiIndex,
displayNameStyle,
timeFormat,
@ -635,7 +684,6 @@ export default defineComponent({
sns,
account,
bookmarkSupported,
shortcutEnabled,
originalMessage,
timestamp,
readableTimestamp,