Merge branch '866-add-new-keyboard-shortcuts' into 'develop'
Resolve "Add new keyboard shortcuts" See merge request funkwhale/funkwhale!801
This commit is contained in:
commit
33ca61d96f
|
@ -0,0 +1 @@
|
||||||
|
New keyboard shortcuts added for enhanced control over audio player (#866)
|
|
@ -4,9 +4,11 @@
|
||||||
<translate translate-context="*/*/*/Noun">Keyboard shortcuts</translate>
|
<translate translate-context="*/*/*/Noun">Keyboard shortcuts</translate>
|
||||||
</header>
|
</header>
|
||||||
<section class="scrolling content">
|
<section class="scrolling content">
|
||||||
|
<div class="ui stackable two column grid">
|
||||||
|
<div class="column">
|
||||||
<table
|
<table
|
||||||
class="ui compact collapsing basic table"
|
class="ui compact basic table"
|
||||||
v-for="section in sections"
|
v-for="section in player"
|
||||||
:key="section.title">
|
:key="section.title">
|
||||||
<caption>{{ section.title }}</caption>
|
<caption>{{ section.title }}</caption>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -16,6 +18,22 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<table
|
||||||
|
class="ui compact basic table"
|
||||||
|
v-for="section in general"
|
||||||
|
:key="section.title">
|
||||||
|
<caption>{{ section.title }}</caption>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="shortcut in section.shortcuts" :key="shortcut.summary">
|
||||||
|
<td>{{ shortcut.summary }}</td>
|
||||||
|
<td><span class="ui label">{{ shortcut.key }}</span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<footer class="actions">
|
<footer class="actions">
|
||||||
<div class="ui cancel button"><translate translate-context="Popup/Keyboard shortcuts/Button.Label/Verb">Close</translate></div>
|
<div class="ui cancel button"><translate translate-context="Popup/Keyboard shortcuts/Button.Label/Verb">Close</translate></div>
|
||||||
|
@ -32,7 +50,7 @@ export default {
|
||||||
Modal,
|
Modal,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
sections () {
|
general () {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: this.$pgettext('Popup/Keyboard shortcuts/Title', 'General shortcuts'),
|
title: this.$pgettext('Popup/Keyboard shortcuts/Title', 'General shortcuts'),
|
||||||
|
@ -40,17 +58,36 @@ export default {
|
||||||
{
|
{
|
||||||
key: 'h',
|
key: 'h',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Show available keyboard shortcuts')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Show available keyboard shortcuts')
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
key: 'shift + f',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Focus searchbar')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'esc',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Unfocus searchbar')
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// space.prevent.exact="togglePlay"
|
// space.prevent.exact="togglePlay"
|
||||||
// ctrl.left.prevent.exact="previous"
|
// ctrl.shift.left.prevent.exact="previous"
|
||||||
// ctrl.right.prevent.exact="next"
|
// ctrl.shift.right.prevent.exact="next"
|
||||||
// ctrl.down.prevent.exact="$store.commit('player/incrementVolume', -0.1)"
|
// shift.down.prevent.exact="$store.commit('player/incrementVolume', -0.1)"
|
||||||
// ctrl.up.prevent.exact="$store.commit('player/incrementVolume', 0.1)"
|
// shift.up.prevent.exact="$store.commit('player/incrementVolume', 0.1)"
|
||||||
|
// right.prevent.exact="seek (5)"
|
||||||
|
// left.prevent.exact="seek (-5)"
|
||||||
|
// shift.right.prevent.exact="seek (30)"
|
||||||
|
// shift.left.prevent.exact="seek (-30)"
|
||||||
|
// m.prevent.exact="toggleMute"
|
||||||
// l.prevent.exact="$store.commit('player/toggleLooping')"
|
// l.prevent.exact="$store.commit('player/toggleLooping')"
|
||||||
// s.prevent.exact="shuffle"
|
// s.prevent.exact="shuffle"
|
||||||
|
// f.prevent.exact="$store.dispatch('favorites/toggle', currentTrack.id)"
|
||||||
|
// q.prevent.exact="clean"
|
||||||
|
|
||||||
|
player () {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
title: this.$pgettext('Popup/Keyboard shortcuts/Title', 'Audio player shortcuts'),
|
title: this.$pgettext('Popup/Keyboard shortcuts/Title', 'Audio player shortcuts'),
|
||||||
shortcuts: [
|
shortcuts: [
|
||||||
|
@ -59,21 +96,41 @@ export default {
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Pause/play the current track')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Pause/play the current track')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'ctrl left',
|
key: 'left',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Seek backwards 5s')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'right',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Seek forwards 5s')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'shift + left',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Seek backwards 30s')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'shift + right',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Seek forwards 30s')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ctrl + shift + left',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Play previous track')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Play previous track')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'ctrl right',
|
key: 'ctrl + shift + right',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Play next track')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Play next track')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'ctrl up',
|
key: 'shift + up',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Increase volume')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Increase volume')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'ctrl down',
|
key: 'shift + down',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Decrease volume')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Decrease volume')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'm',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Toggle mute')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'l',
|
key: 'l',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Toggle queue looping')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Toggle queue looping')
|
||||||
|
@ -82,6 +139,14 @@ export default {
|
||||||
key: 's',
|
key: 's',
|
||||||
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Shuffle queue')
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Shuffle queue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'q',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Clear queue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'f',
|
||||||
|
summary: this.$pgettext('Popup/Keyboard shortcuts/Table.Label/Verb', 'Toggle favorite')
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -206,12 +206,19 @@
|
||||||
</div>
|
</div>
|
||||||
<GlobalEvents
|
<GlobalEvents
|
||||||
@keydown.space.prevent.exact="togglePlay"
|
@keydown.space.prevent.exact="togglePlay"
|
||||||
@keydown.ctrl.left.prevent.exact="previous"
|
@keydown.ctrl.shift.left.prevent.exact="previous"
|
||||||
@keydown.ctrl.right.prevent.exact="next"
|
@keydown.ctrl.shift.right.prevent.exact="next"
|
||||||
@keydown.ctrl.down.prevent.exact="$store.commit('player/incrementVolume', -0.1)"
|
@keydown.shift.down.prevent.exact="$store.commit('player/incrementVolume', -0.1)"
|
||||||
@keydown.ctrl.up.prevent.exact="$store.commit('player/incrementVolume', 0.1)"
|
@keydown.shift.up.prevent.exact="$store.commit('player/incrementVolume', 0.1)"
|
||||||
|
@keydown.right.prevent.exact="seek (5)"
|
||||||
|
@keydown.left.prevent.exact="seek (-5)"
|
||||||
|
@keydown.shift.right.prevent.exact="seek (30)"
|
||||||
|
@keydown.shift.left.prevent.exact="seek (-30)"
|
||||||
|
@keydown.m.prevent.exact="toggleMute"
|
||||||
@keydown.l.prevent.exact="$store.commit('player/toggleLooping')"
|
@keydown.l.prevent.exact="$store.commit('player/toggleLooping')"
|
||||||
@keydown.s.prevent.exact="shuffle"
|
@keydown.s.prevent.exact="shuffle"
|
||||||
|
@keydown.f.prevent.exact="$store.dispatch('favorites/toggle', currentTrack.id)"
|
||||||
|
@keydown.q.prevent.exact="clean"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -294,6 +301,7 @@ export default {
|
||||||
mute: "player/mute",
|
mute: "player/mute",
|
||||||
unmute: "player/unmute",
|
unmute: "player/unmute",
|
||||||
clean: "queue/clean",
|
clean: "queue/clean",
|
||||||
|
toggleMute: "player/toggleMute",
|
||||||
}),
|
}),
|
||||||
async getTrackData (trackData) {
|
async getTrackData (trackData) {
|
||||||
let data = null
|
let data = null
|
||||||
|
@ -489,6 +497,21 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
seek (step) {
|
||||||
|
if (step > 0) {
|
||||||
|
// seek right
|
||||||
|
if (this.currentTime + step < this.duration) {
|
||||||
|
this.$store.dispatch('player/updateProgress', (this.currentTime + step))
|
||||||
|
} else {
|
||||||
|
this.next() // parenthesis where missing here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// seek left
|
||||||
|
let position = Math.max(this.currentTime + step, 0)
|
||||||
|
this.$store.dispatch('player/updateProgress', position)
|
||||||
|
}
|
||||||
|
},
|
||||||
observeProgress: function (enable) {
|
observeProgress: function (enable) {
|
||||||
let self = this
|
let self = this
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ui fluid category search">
|
<div class="ui fluid category search">
|
||||||
<slot></slot><div class="ui icon input">
|
<slot></slot><div class="ui icon input">
|
||||||
<input class="prompt" name="search" :placeholder="labels.placeholder" type="text">
|
<input class="prompt" ref="search" name="search" :placeholder="labels.placeholder" type="text" @keydown.esc="$event.target.blur()">
|
||||||
<i class="search icon"></i>
|
<i class="search icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="results"></div>
|
<div class="results"></div>
|
||||||
<slot name="after"></slot>
|
<slot name="after"></slot>
|
||||||
|
<GlobalEvents
|
||||||
|
@keydown.shift.f.prevent.exact="focusSearch"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import jQuery from 'jquery'
|
import jQuery from 'jquery'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
import GlobalEvents from "@/components/utils/global-events"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
GlobalEvents,
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
labels () {
|
labels () {
|
||||||
return {
|
return {
|
||||||
|
@ -104,6 +111,11 @@ export default {
|
||||||
url: this.$store.getters['instance/absoluteUrl']('api/v1/search?query={query}')
|
url: this.$store.getters['instance/absoluteUrl']('api/v1/search?query={query}')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
focusSearch () {
|
||||||
|
this.$refs.search.focus()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -109,6 +109,15 @@ export default {
|
||||||
}, 3000)
|
}, 3000)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
toggleMute({commit, state}) {
|
||||||
|
if (state.volume > 0) {
|
||||||
|
commit('tempVolume', state.volume)
|
||||||
|
commit('volume', 0)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
commit('volume', state.tempVolume)
|
||||||
|
}
|
||||||
|
},
|
||||||
trackListened ({commit, rootState}, track) {
|
trackListened ({commit, rootState}, track) {
|
||||||
if (!rootState.auth.authenticated) {
|
if (!rootState.auth.authenticated) {
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue