172 lines
4.4 KiB
Vue
172 lines
4.4 KiB
Vue
<template>
|
|
<el-dialog v-model="jumpModal" width="440px" class="jump-modal">
|
|
<el-form class="jump-form" v-on:submit.prevent="jump">
|
|
<div class="channel">
|
|
<input
|
|
type="text"
|
|
v-model="channel"
|
|
:placeholder="$t('modals.jump.jump_to')"
|
|
ref="channel"
|
|
v-shortkey="shortcutEnabled ? { next: ['arrowdown'], prev: ['arrowup'], select: ['enter'] } : {}"
|
|
@shortkey="handleKey"
|
|
/>
|
|
<ul class="channel-list">
|
|
<li
|
|
v-for="c in filterdChannel"
|
|
:class="c.name === selectedChannel.name ? 'channel-list-item selected' : 'channel-list-item'"
|
|
@click="jump(c)"
|
|
@mouseover="changeSelected(c)"
|
|
>
|
|
{{ c.name }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<!-- Dummy form to guard submitting with enter -->
|
|
<el-form-item class="hidden">
|
|
<el-input></el-input>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState } from 'vuex'
|
|
|
|
export default {
|
|
name: 'jump',
|
|
computed: {
|
|
...mapState('TimelineSpace/Modals/Jump', {
|
|
channelList: state => state.defaultChannelList.concat(state.tagChannelList).concat(state.listChannelList),
|
|
selectedChannel: state => state.selectedChannel
|
|
}),
|
|
channel: {
|
|
get() {
|
|
return this.$store.state.TimelineSpace.Modals.Jump.channel
|
|
},
|
|
set(value) {
|
|
this.$store.commit('TimelineSpace/Modals/Jump/updateChannel', value)
|
|
}
|
|
},
|
|
filterdChannel() {
|
|
return this.filterChannelForm()
|
|
},
|
|
jumpModal: {
|
|
get() {
|
|
return this.$store.state.TimelineSpace.Modals.Jump.modalOpen
|
|
},
|
|
set(value) {
|
|
this.$store.commit('TimelineSpace/Modals/Jump/changeModal', value)
|
|
}
|
|
},
|
|
shortcutEnabled: function () {
|
|
return this.jumpModal
|
|
}
|
|
},
|
|
watch: {
|
|
channel: function (_newChannel, _oldChannel) {
|
|
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', this.filterChannelForm()[0])
|
|
},
|
|
jumpModal: function (newModal, oldModal) {
|
|
if (!oldModal && newModal) {
|
|
this.$nextTick(function () {
|
|
this.$store.dispatch('TimelineSpace/Modals/Jump/syncListChannel')
|
|
this.$store.dispatch('TimelineSpace/Modals/Jump/syncTagChannel')
|
|
this.$refs.channel.focus()
|
|
})
|
|
} else {
|
|
this.channel = ''
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
filterChannelForm() {
|
|
return this.channelList.filter(c => {
|
|
return c.name.toLowerCase().indexOf(this.channel.toLowerCase()) !== -1
|
|
})
|
|
},
|
|
nextChannel() {
|
|
const filterd = this.filterChannelForm()
|
|
const i = filterd.findIndex(e => {
|
|
return e.name === this.selectedChannel.name
|
|
})
|
|
if (i !== undefined && i < filterd.length - 1) {
|
|
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', filterd[i + 1])
|
|
}
|
|
},
|
|
prevChannel() {
|
|
const filterd = this.filterChannelForm()
|
|
const i = filterd.findIndex(e => {
|
|
return e.name === this.selectedChannel.name
|
|
})
|
|
if (i !== undefined && i > 0) {
|
|
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', filterd[i - 1])
|
|
}
|
|
},
|
|
changeSelected(channel) {
|
|
this.$store.commit('TimelineSpace/Modals/Jump/changeSelected', channel)
|
|
},
|
|
jumpCurrentSelected() {
|
|
if (this.jumpModal) {
|
|
this.$store.dispatch('TimelineSpace/Modals/Jump/jumpCurrentSelected')
|
|
}
|
|
},
|
|
jump(channel) {
|
|
this.$store.dispatch('TimelineSpace/Modals/Jump/jump', channel)
|
|
},
|
|
handleKey(event) {
|
|
switch (event.srcKey) {
|
|
case 'next':
|
|
this.nextChannel()
|
|
break
|
|
case 'prev':
|
|
this.prevChannel()
|
|
break
|
|
case 'select':
|
|
this.jumpCurrentSelected()
|
|
break
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.jump-form {
|
|
.channel {
|
|
input {
|
|
font-size: 32px;
|
|
line-height: 54px;
|
|
width: 100%;
|
|
outline: 0;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 8px;
|
|
padding: 8px;
|
|
color: #303133;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.channel-list {
|
|
list-style: none;
|
|
font-size: 16px;
|
|
padding: 0;
|
|
|
|
.channel-list-item {
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.selected {
|
|
background-color: #409eff;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
.hidden {
|
|
display: none;
|
|
}
|
|
}
|
|
</style>
|