refs #3300 Enable shortcut to move focus on statuses in Notifications
This commit is contained in:
parent
33c4694774
commit
b045143035
|
@ -16,8 +16,6 @@
|
|||
:overlaid="modalOpened"
|
||||
:filters="filters"
|
||||
v-on:update="updateToot"
|
||||
@focusNext="focusNext"
|
||||
@focusPrev="focusPrev"
|
||||
@focusRight="focusSidebar"
|
||||
@selectNotification="focusNotification(item)"
|
||||
>
|
||||
|
@ -36,6 +34,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed, onMounted, onBeforeUpdate, onBeforeUnmount, onUnmounted, watch } from 'vue'
|
||||
import { useMagicKeys, whenever, and } from '@vueuse/core'
|
||||
import moment from 'moment'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Entity } from 'megalodon'
|
||||
|
@ -62,6 +61,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)
|
||||
|
@ -77,20 +77,12 @@ export default defineComponent({
|
|||
const scrolling = computed(() => store.state.TimelineSpace.Contents.Notifications.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 handledNotifications = computed(() => store.getters[`${space}/handledNotifications`])
|
||||
const currentFocusedIndex = computed(() => notifications.value.findIndex(notification => focusedId.value === notification.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)
|
||||
|
||||
onMounted(() => {
|
||||
store.commit(`TimelineSpace/SideMenu/${SIDE_MENU_MUTATION.CHANGE_UNREAD_NOTIFICATIONS}`, false)
|
||||
store.dispatch(`${space}/${ACTION_TYPES.RESET_BADGE}`)
|
||||
|
@ -151,6 +143,24 @@ 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)
|
||||
store.commit(`${space}/${ACTION_TYPES.RESET_BADGE}`)
|
||||
}
|
||||
})
|
||||
whenever(and(j, shortcutEnabled), () => {
|
||||
if (focusedId.value === null) {
|
||||
focusedId.value = handledNotifications.value[0].id
|
||||
} else {
|
||||
focusNext()
|
||||
}
|
||||
})
|
||||
whenever(and(k, shortcutEnabled), () => {
|
||||
focusPrev()
|
||||
})
|
||||
|
||||
const onScroll = (event: Event) => {
|
||||
if (moment().diff(resizeTime.value) < 500) {
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
reactionType="favourite"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -18,8 +16,6 @@
|
|||
:message="message"
|
||||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -29,8 +25,6 @@
|
|||
:message="message"
|
||||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -43,8 +37,6 @@
|
|||
:overlaid="overlaid"
|
||||
v-on:update="updateToot"
|
||||
v-on:delete="deleteToot"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -56,8 +48,6 @@
|
|||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
reactionType="quote"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -69,21 +59,6 @@
|
|||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
reactionType="reblog"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
</StatusReaction>
|
||||
<StatusReaction
|
||||
v-else-if="message.type === 'emoji_reaction'"
|
||||
:message="message"
|
||||
:filters="filters"
|
||||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
reactionType="reaction"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -94,8 +69,6 @@
|
|||
:filters="filters"
|
||||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -107,8 +80,6 @@
|
|||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
reactionType="poll-vote"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
@ -120,8 +91,6 @@
|
|||
:focused="focused"
|
||||
:overlaid="overlaid"
|
||||
reactionType="poll-expired"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@select="$emit('selectNotification')"
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="relationship" tabIndex="0" @click="$emit('select')" role="article" aria-label="follow event">
|
||||
<div class="relationship" tabIndex="0" @click="$emit('select')" role="article" aria-label="follow event" ref="notificationRef">
|
||||
<div class="follow">
|
||||
<div class="action">
|
||||
<div class="action-mark">
|
||||
|
@ -28,7 +28,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed, toRefs } from 'vue'
|
||||
import { defineComponent, PropType, computed, toRefs, ref, nextTick, watch } from 'vue'
|
||||
import { Entity } from 'megalodon'
|
||||
import { useStore } from '@/store'
|
||||
import FailoverImg from '@/components/atoms/FailoverImg.vue'
|
||||
|
@ -56,12 +56,25 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
setup(props) {
|
||||
const { focused, overlaid } = toRefs(props)
|
||||
const { focused } = toRefs(props)
|
||||
const store = useStore()
|
||||
const notificationRef = ref<any>(null)
|
||||
|
||||
const shortcutEnabled = computed(() => focused.value && !overlaid.value)
|
||||
// const shortcutEnabled = computed(() => focused.value && !overlaid.value)
|
||||
const displayNameStyle = computed(() => store.state.App.displayNameStyle)
|
||||
|
||||
watch(focused, (newVal, oldVal) => {
|
||||
if (newVal) {
|
||||
nextTick(() => {
|
||||
notificationRef.value.focus()
|
||||
})
|
||||
} else if (oldVal && !newVal) {
|
||||
nextTick(() => {
|
||||
notificationRef.value.blur()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const username = (account: Entity.Account) => usernameWithStyle(account, displayNameStyle.value)
|
||||
const openUser = (account: Entity.Account) => {
|
||||
store.dispatch(`TimelineSpace/Contents/SideBar/${SIDEBAR_ACTION.OPEN_ACCOUNT_COMPONENT}`)
|
||||
|
@ -70,7 +83,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return {
|
||||
shortcutEnabled,
|
||||
notificationRef,
|
||||
username,
|
||||
openUser
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="relationship" tabIndex="0" ref="status" @click="$emit('select')" role="article" aria-label="follow event">
|
||||
<div class="relationship" tabIndex="0" @click="$emit('select')" role="article" aria-label="follow event" ref="notificationRef">
|
||||
<div class="follow-request">
|
||||
<div class="action">
|
||||
<div class="action-mark">
|
||||
|
@ -28,7 +28,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed, toRefs } from 'vue'
|
||||
import { defineComponent, PropType, computed, toRefs, ref, watch, nextTick } from 'vue'
|
||||
import { Entity } from 'megalodon'
|
||||
import { useStore } from '@/store'
|
||||
import FailoverImg from '@/components/atoms/FailoverImg.vue'
|
||||
|
@ -56,12 +56,25 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
setup(props) {
|
||||
const { focused, overlaid } = toRefs(props)
|
||||
const { focused } = toRefs(props)
|
||||
const store = useStore()
|
||||
const notificationRef = ref<any>(null)
|
||||
|
||||
const shortcutEnabled = computed(() => focused.value && !overlaid.value)
|
||||
// const shortcutEnabled = computed(() => focused.value && !overlaid.value)
|
||||
const displayNameStyle = computed(() => store.state.App.displayNameStyle)
|
||||
|
||||
watch(focused, (newVal, oldVal) => {
|
||||
if (newVal) {
|
||||
nextTick(() => {
|
||||
notificationRef.value.focus()
|
||||
})
|
||||
} else if (oldVal && !newVal) {
|
||||
nextTick(() => {
|
||||
notificationRef.value.blur()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const username = (account: Entity.Account) => usernameWithStyle(account, displayNameStyle.value)
|
||||
const openUser = (account: Entity.Account) => {
|
||||
store.dispatch(`TimelineSpace/Contents/SideBar/${SIDEBAR_ACTION.OPEN_ACCOUNT_COMPONENT}`)
|
||||
|
@ -70,7 +83,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return {
|
||||
shortcutEnabled,
|
||||
notificationRef,
|
||||
username,
|
||||
openUser
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
:overlaid="overlaid"
|
||||
v-on:update="updateToot"
|
||||
v-on:delete="deleteToot"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@selectToot="$emit('select')"
|
||||
>
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
:overlaid="overlaid"
|
||||
v-on:update="updateToot"
|
||||
v-on:delete="deleteToot"
|
||||
@focusNext="$emit('focusNext')"
|
||||
@focusPrev="$emit('focusPrev')"
|
||||
@focusRight="$emit('focusRight')"
|
||||
@selectToot="$emit('select')"
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="status" tabIndex="0" @click="$emit('select')" role="article" :aria-label="reactionType">
|
||||
<div class="status" tabIndex="0" @click="$emit('select')" role="article" :aria-label="reactionType" ref="notificationRef">
|
||||
<div v-show="filtered" class="filtered">Filtered</div>
|
||||
<div v-show="!filtered" class="status-reaction">
|
||||
<div class="action">
|
||||
|
@ -94,7 +94,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, toRefs, ref, PropType } from 'vue'
|
||||
import { defineComponent, computed, toRefs, ref, PropType, watch, nextTick } from 'vue'
|
||||
import { Entity } from 'megalodon'
|
||||
import moment from 'moment'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
@ -142,16 +142,17 @@ export default defineComponent({
|
|||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const { focused, overlaid, message, filters, reactionType } = toRefs(props)
|
||||
const { focused, message, filters, reactionType } = toRefs(props)
|
||||
|
||||
const showContent = ref<boolean>(false)
|
||||
const showAttachments = ref<boolean>(false)
|
||||
const notificationRef = ref<any>(null)
|
||||
|
||||
const displayNameStyle = computed(() => store.state.App.displayNameStyle)
|
||||
const timeFormat = computed(() => store.state.App.timeFormat)
|
||||
const language = computed(() => store.state.App.language)
|
||||
const hideAllAttachments = computed(() => store.state.App.hideAllAttachments)
|
||||
const shortcutEnabled = computed(() => focused.value && !overlaid.value)
|
||||
// const shortcutEnabled = computed(() => focused.value && !overlaid.value)
|
||||
const timestamp = computed(() => parseDatetime(message.value.created_at, timeFormat.value, language.value))
|
||||
const readableTimestamp = computed(() => {
|
||||
moment.locale(language.value)
|
||||
|
@ -205,6 +206,18 @@ export default defineComponent({
|
|||
}
|
||||
})
|
||||
|
||||
watch(focused, (newVal, oldVal) => {
|
||||
if (newVal) {
|
||||
nextTick(() => {
|
||||
notificationRef.value.focus()
|
||||
})
|
||||
} else if (oldVal && !newVal) {
|
||||
nextTick(() => {
|
||||
notificationRef.value.blur()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const username = (account: Entity.Account) => usernameWithStyle(account, displayNameStyle.value)
|
||||
const tootClick = (e: MouseEvent) => {
|
||||
const parsedTag = findTag(e.target as HTMLElement, 'status-reaction')
|
||||
|
@ -251,11 +264,11 @@ export default defineComponent({
|
|||
return {
|
||||
showContent,
|
||||
showAttachments,
|
||||
notificationRef,
|
||||
displayNameStyle,
|
||||
timeFormat,
|
||||
language,
|
||||
hideAllAttachments,
|
||||
shortcutEnabled,
|
||||
timestamp,
|
||||
readableTimestamp,
|
||||
username,
|
||||
|
|
Loading…
Reference in New Issue