Merge branch 'a0js-add-volume-control'
This commit is contained in:
commit
c072bccc58
@ -47,19 +47,36 @@
|
|||||||
<!-- Controls right --->
|
<!-- Controls right --->
|
||||||
<div class="col-auto col-sm p-0">
|
<div class="col-auto col-sm p-0">
|
||||||
<div class="d-flex flex-nowrap justify-content-end pr-3">
|
<div class="d-flex flex-nowrap justify-content-end pr-3">
|
||||||
|
<div class="m-0 d-none d-md-inline-flex align-items-center">
|
||||||
|
<b-button variant="link" @click="toggleMute">
|
||||||
|
<Icon :icon="muteActive ? 'volume-mute-fill' : 'volume-up-fill'" />
|
||||||
|
</b-button>
|
||||||
|
<b-form-input type="range" min="0" max="1" step="0.05"
|
||||||
|
style="width: 120px; min-width: 0; padding-right: 0.75rem"
|
||||||
|
:title="`Volume: ${Math.round(volume * 100)}%`"
|
||||||
|
:value="muteActive ? 0.0 : volume" @input="setVolume" />
|
||||||
<b-button variant="link"
|
<b-button variant="link"
|
||||||
class="m-0 d-none d-sm-inline-block"
|
class="m-0" :class="{ 'text-primary': shuffleActive }"
|
||||||
:class="{ 'text-primary': shuffleActive }"
|
|
||||||
@click="toggleShuffle">
|
@click="toggleShuffle">
|
||||||
<Icon icon="shuffle" />
|
<Icon icon="shuffle" />
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button variant="link"
|
<b-button variant="link"
|
||||||
class="m-0 d-none d-sm-inline-block "
|
class="m-0" :class="{ 'text-primary': repeatActive }"
|
||||||
:class="{ 'text-primary': repeatActive }"
|
|
||||||
@click="toggleRepeat">
|
@click="toggleRepeat">
|
||||||
<Icon icon="arrow-repeat" />
|
<Icon icon="arrow-repeat" />
|
||||||
</b-button>
|
</b-button>
|
||||||
<OverflowMenu class="d-sm-none">
|
</div>
|
||||||
|
<OverflowMenu class="d-md-none">
|
||||||
|
<b-dropdown-text>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<strong>Volume</strong>
|
||||||
|
<b-form-input
|
||||||
|
class="px-2" style="width: 120px"
|
||||||
|
type="range" min="0" max="1" step="0.05"
|
||||||
|
:value="volume" @input="setVolume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</b-dropdown-text>
|
||||||
<b-dropdown-text>
|
<b-dropdown-text>
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<strong>Repeat</strong>
|
<strong>Repeat</strong>
|
||||||
@ -96,6 +113,10 @@
|
|||||||
height: auto;
|
height: auto;
|
||||||
max-height: 100px;
|
max-height: 100px;
|
||||||
}
|
}
|
||||||
|
.b-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
@ -108,7 +129,9 @@
|
|||||||
currentTime: (state: any) => state.currentTime,
|
currentTime: (state: any) => state.currentTime,
|
||||||
repeatActive: (state: any) => state.repeat,
|
repeatActive: (state: any) => state.repeat,
|
||||||
shuffleActive: (state: any) => state.shuffle,
|
shuffleActive: (state: any) => state.shuffle,
|
||||||
|
muteActive: (state: any) => state.mute,
|
||||||
visible: (state: any) => state.queue.length > 0,
|
visible: (state: any) => state.queue.length > 0,
|
||||||
|
volume: (state: any) => state.volume,
|
||||||
}),
|
}),
|
||||||
...mapGetters('player', [
|
...mapGetters('player', [
|
||||||
'track',
|
'track',
|
||||||
@ -122,6 +145,7 @@
|
|||||||
'previous',
|
'previous',
|
||||||
'toggleRepeat',
|
'toggleRepeat',
|
||||||
'toggleShuffle',
|
'toggleShuffle',
|
||||||
|
'toggleMute',
|
||||||
]),
|
]),
|
||||||
seek(event: any) {
|
seek(event: any) {
|
||||||
if (event.target) {
|
if (event.target) {
|
||||||
@ -130,6 +154,9 @@
|
|||||||
return this.$store.dispatch('player/seek', value)
|
return this.$store.dispatch('player/seek', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setVolume(volume: any) {
|
||||||
|
return this.$store.dispatch('player/setVolume', parseFloat(volume))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,6 +8,9 @@ const storedQueueIndex = parseInt(localStorage.getItem('queueIndex') || '-1')
|
|||||||
if (storedQueueIndex > -1 && storedQueueIndex < storedQueue.length) {
|
if (storedQueueIndex > -1 && storedQueueIndex < storedQueue.length) {
|
||||||
audio.src = storedQueue[storedQueueIndex].url
|
audio.src = storedQueue[storedQueueIndex].url
|
||||||
}
|
}
|
||||||
|
const storedVolume = parseFloat(localStorage.getItem('player.volume') || '1.0')
|
||||||
|
const storedMuteState = localStorage.getItem('player.mute') === 'true'
|
||||||
|
audio.volume = storedMuteState ? 0.0 : storedVolume
|
||||||
const mediaSession: MediaSession | undefined = navigator.mediaSession
|
const mediaSession: MediaSession | undefined = navigator.mediaSession
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@ -19,6 +22,8 @@ interface State {
|
|||||||
currentTime: number; // position of current track in seconds
|
currentTime: number; // position of current track in seconds
|
||||||
repeat: boolean;
|
repeat: boolean;
|
||||||
shuffle: boolean;
|
shuffle: boolean;
|
||||||
|
mute: boolean;
|
||||||
|
volume: number; // integer between 0 and 1 representing the volume of the player
|
||||||
}
|
}
|
||||||
|
|
||||||
export const playerModule: Module<State, any> = {
|
export const playerModule: Module<State, any> = {
|
||||||
@ -32,6 +37,8 @@ export const playerModule: Module<State, any> = {
|
|||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
repeat: localStorage.getItem('player.repeat') !== 'false',
|
repeat: localStorage.getItem('player.repeat') !== 'false',
|
||||||
shuffle: localStorage.getItem('player.shuffle') === 'true',
|
shuffle: localStorage.getItem('player.shuffle') === 'true',
|
||||||
|
mute: storedMuteState,
|
||||||
|
volume: storedVolume,
|
||||||
},
|
},
|
||||||
|
|
||||||
mutations: {
|
mutations: {
|
||||||
@ -55,6 +62,10 @@ export const playerModule: Module<State, any> = {
|
|||||||
state.shuffle = enable
|
state.shuffle = enable
|
||||||
localStorage.setItem('player.shuffle', enable)
|
localStorage.setItem('player.shuffle', enable)
|
||||||
},
|
},
|
||||||
|
setMute(state, enable) {
|
||||||
|
state.mute = enable
|
||||||
|
localStorage.setItem('player.mute', enable)
|
||||||
|
},
|
||||||
setQueue(state, queue) {
|
setQueue(state, queue) {
|
||||||
state.queue = queue
|
state.queue = queue
|
||||||
state.queueIndex = -1
|
state.queueIndex = -1
|
||||||
@ -102,6 +113,11 @@ export const playerModule: Module<State, any> = {
|
|||||||
setScrobbled(state) {
|
setScrobbled(state) {
|
||||||
state.scrobbled = true
|
state.scrobbled = true
|
||||||
},
|
},
|
||||||
|
setVolume(state, value: number) {
|
||||||
|
state.volume = value
|
||||||
|
state.mute = value <= 0.0
|
||||||
|
localStorage.setItem('player.volume', String(value))
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
@ -170,12 +186,20 @@ export const playerModule: Module<State, any> = {
|
|||||||
toggleShuffle({ commit, state }) {
|
toggleShuffle({ commit, state }) {
|
||||||
commit('setShuffle', !state.shuffle)
|
commit('setShuffle', !state.shuffle)
|
||||||
},
|
},
|
||||||
|
toggleMute({ commit, state }) {
|
||||||
|
commit('setMute', !state.mute)
|
||||||
|
audio.volume = state.mute ? 0.0 : state.volume
|
||||||
|
},
|
||||||
addToQueue({ commit }, track) {
|
addToQueue({ commit }, track) {
|
||||||
commit('addToQueue', track)
|
commit('addToQueue', track)
|
||||||
},
|
},
|
||||||
setNextInQueue({ commit }, track) {
|
setNextInQueue({ commit }, track) {
|
||||||
commit('setNextInQueue', track)
|
commit('setNextInQueue', track)
|
||||||
},
|
},
|
||||||
|
setVolume({ commit }, value) {
|
||||||
|
audio.volume = value
|
||||||
|
commit('setVolume', value)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
BIconPersonCircle,
|
BIconPersonCircle,
|
||||||
BIconRss,
|
BIconRss,
|
||||||
BIconX,
|
BIconX,
|
||||||
|
BIconVolumeUpFill,
|
||||||
|
BIconVolumeMuteFill,
|
||||||
} from 'bootstrap-vue'
|
} from 'bootstrap-vue'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
@ -56,6 +58,8 @@
|
|||||||
BIconPersonCircle,
|
BIconPersonCircle,
|
||||||
BIconRss,
|
BIconRss,
|
||||||
BIconX,
|
BIconX,
|
||||||
|
BIconVolumeUpFill,
|
||||||
|
BIconVolumeMuteFill,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
icon: { type: String, required: true }
|
icon: { type: String, required: true }
|
||||||
|
@ -34,6 +34,9 @@ $dropdown-divider-bg: $theme-elevation-2;
|
|||||||
$input-bg: $theme-elevation-2;
|
$input-bg: $theme-elevation-2;
|
||||||
$input-border-color: $theme-elevation-2;
|
$input-border-color: $theme-elevation-2;
|
||||||
$input-color: $theme-text;
|
$input-color: $theme-text;
|
||||||
|
$custom-range-track-height: 0.1rem;
|
||||||
|
$custom-range-thumb-bg: $theme-text;
|
||||||
|
$custom-range-track-bg: $theme-text-muted;
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
$progress-bg: rgb(35, 35, 35);
|
$progress-bg: rgb(35, 35, 35);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user