diff --git a/apps/music/frontend/src/views/PlayerView.vue b/apps/music/frontend/src/views/PlayerView.vue index 899fcdf..131fe69 100644 --- a/apps/music/frontend/src/views/PlayerView.vue +++ b/apps/music/frontend/src/views/PlayerView.vue @@ -230,6 +230,20 @@
{{ fmtTime(duration) }} + + @@ -336,6 +350,37 @@ const activeTagName = ref(null) const search = ref('') const sortMode = ref(localStorage.getItem('music.sort') || 'name') const repeatOne = ref(false) +const volume = ref(parseFloat(localStorage.getItem('music.vol') || '1')) +const muted = ref(localStorage.getItem('music.muted') === '1') + +const volIcon = computed(() => { + if (muted.value || volume.value === 0) return '🔇' + if (volume.value < 0.34) return '🔈' + if (volume.value < 0.67) return '🔉' + return '🔊' +}) + +function applyVolume() { + if (audioEl.value) { + audioEl.value.volume = volume.value + audioEl.value.muted = muted.value + } +} + +function onVolumeInput(e) { + const v = parseInt(e.target.value, 10) / 100 + volume.value = isNaN(v) ? 0 : Math.max(0, Math.min(1, v)) + if (volume.value > 0 && muted.value) muted.value = false + localStorage.setItem('music.vol', String(volume.value)) + localStorage.setItem('music.muted', muted.value ? '1' : '0') + applyVolume() +} + +function toggleMute() { + muted.value = !muted.value + localStorage.setItem('music.muted', muted.value ? '1' : '0') + applyVolume() +} const audioEl = ref(null) const lyricsBoxEl = ref(null) @@ -650,6 +695,7 @@ function onTimeUpdate(e) { function onLoaded(e) { duration.value = e.target.duration || 0 + applyVolume() } function onEnded() { @@ -1364,6 +1410,38 @@ onBeforeUnmount(() => { text-align: center; } +.vol-icon { font-size: 16px; width: 32px; height: 32px; } +.vol-slider { + -webkit-appearance: none; + appearance: none; + width: 90px; + height: 4px; + background: var(--border); + border-radius: 2px; + cursor: pointer; +} +.vol-slider:focus { outline: none; } +.vol-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 12px; + height: 12px; + background: var(--accent-strong); + border-radius: 50%; + cursor: pointer; +} +.vol-slider::-moz-range-thumb { + width: 12px; + height: 12px; + background: var(--accent-strong); + border: none; + border-radius: 50%; + cursor: pointer; +} +@media (max-width: 768px) { + .vol-slider { width: 60px; } +} + /* Chat sidebar */ .chat { width: 320px;