1
0
Fork 0
mirror of https://github.com/heyarne/airsonic-ui.git synced 2026-05-07 02:33:39 +02:00

Implement always-visible volume controls

This commit is contained in:
heyarne 2019-02-20 18:19:29 +01:00
commit 054e55f8b6
4 changed files with 91 additions and 10 deletions

View file

@ -23,7 +23,8 @@
:current-src (.-currentSrc elem) :current-src (.-currentSrc elem)
:current-time (.-currentTime elem) :current-time (.-currentTime elem)
:seekable (normalize-time-ranges (.-seekable elem)) :seekable (normalize-time-ranges (.-seekable elem))
:buffered (normalize-time-ranges (.-buffered elem))}) :buffered (normalize-time-ranges (.-buffered elem))
:volume (.-volume elem)})
; explanation of these events: https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery/Cross-browser_audio_basics ; explanation of these events: https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery/Cross-browser_audio_basics
@ -71,6 +72,11 @@
(set! (. @audio -currentTime) (set! (. @audio -currentTime)
(* percentage duration)))) (* percentage duration))))
(rf/reg-fx
:audio/set-volume
(fn [percentage]
(set! (. @audio -volume) percentage)))
;; subscriptions ;; subscriptions
(defn summary (defn summary

View file

@ -67,3 +67,9 @@
(fn [{:keys [db]} [_ percentage]] (fn [{:keys [db]} [_ percentage]]
(let [duration (:duration (playlist/peek (get-in db [:audio :playlist])))] (let [duration (:duration (playlist/peek (get-in db [:audio :playlist])))]
{:audio/seek [percentage duration]}))) {:audio/seek [percentage duration]})))
(rf/reg-event-fx
:audio-player/set-volume
(fn [{:keys [db]} [_ percentage]]
{:db (assoc-in db [:audio :playback-status :volume] percentage)
:audio/set-volume percentage}))

View file

@ -53,7 +53,7 @@
[:span.song-title (:title song)]]]]) [:span.song-title (:title song)]]]])
(defn playback-controls [is-playing?] (defn playback-controls [is-playing?]
[:div.playback-controls [:div.button-controls.playback-controls
[:div.field.has-addons [:div.field.has-addons
(let [buttons [[:media-step-backward :audio-player/previous-song] (let [buttons [[:media-step-backward :audio-player/previous-song]
[(if is-playing? :media-pause :media-play) :audio-player/toggle-play-pause] [(if is-playing? :media-pause :media-play) :audio-player/toggle-play-pause]
@ -78,6 +78,33 @@
(second))] (second))]
(h/muted-dispatch [:audio-player/set-repeat-mode next-mode]))) (h/muted-dispatch [:audio-player/set-repeat-mode next-mode])))
(defn set-volume [ev]
(let [y-ratio (/ (.. ev -nativeEvent -offsetY)
(.. ev -target getBoundingClientRect -height))]
(dispatch [:audio-player/set-volume (- 1 y-ratio)])))
(defn volume-controls [playback-status]
(let [y-pos (* (- 1 (:volume playback-status)) 100)]
[:div.button-controls.volume-controls
[:div.button-menu
[:svg.volume-bar {:width "100%", :height "100%"}
;; the translate(...) makes the 1px rects look smoother
[:g {:transform "translate(-0.5,0)"}
;; background line
[:rect.inactive {:x "50%", :y 0, :width 1, :height "100%"}]
;; below are the line and circle that show the current volume
[:rect.active {:x "50%", :y (str y-pos "%"),
:width 1, :height (str (- 100 y-pos) "%")}]]
[:circle.active {:cx "50%", :cy (str y-pos "%"), :r 3}]
[:rect.click-dummy {:x 0, :y 0, :width "100%", :height "100%"
:on-mouse-down set-volume
:on-mouse-up set-volume
;; fire the on-mouse-move only when left mouse button is pressed
:on-mouse-move #(when (= 1 (.-buttons %))
(set-volume %))}]]]
[:p.control>button.button.is-light
[icon :volume-high]]]))
(defn playback-mode-controls [playlist] (defn playback-mode-controls [playlist]
(let [{:keys [repeat-mode playback-mode]} playlist (let [{:keys [repeat-mode playback-mode]} playlist
button :p.control>button.button.is-light button :p.control>button.button.is-light
@ -90,7 +117,7 @@
:repeat-all "Repeating current queue, click to repeat current track" :repeat-all "Repeating current queue, click to repeat current track"
:repeat-single "Repeating current track, click to repeat none" :repeat-single "Repeating current track, click to repeat none"
"Click to repeat current queue")] "Click to repeat current queue")]
[:div.playback-mode-controls [:div.button-controls.playback-mode-controls
[:div.button-group>div.field.has-addons [:div.button-group>div.field.has-addons
^{:key :shuffle-button} [shuffle-button {:on-click (toggle-shuffle playback-mode) ^{:key :shuffle-button} [shuffle-button {:on-click (toggle-shuffle playback-mode)
:title "Shuffle"} [icon :random]] :title "Shuffle"} [icon :random]]
@ -109,6 +136,7 @@
[playback-info current-song playback-status] [playback-info current-song playback-status]
[progress-indicators current-song playback-status] [progress-indicators current-song playback-status]
[playback-controls is-playing?] [playback-controls is-playing?]
[volume-controls playback-status]
[playback-mode-controls playlist]] [playback-mode-controls playlist]]
;; not playing anything ;; not playing anything
[:p.navbar-item.idle-notification "No audio playing"])])) [:p.navbar-item.idle-notification "No audio playing"])]))

View file

@ -122,14 +122,55 @@
fill: $dark-invert fill: $dark-invert
// buttons to control current playback and playlist behavior // buttons to control current playback and playlist behavior
.playback-controls, .button-controls
.playback-mode-controls position: relative
flex-shrink: 0 flex-shrink: 0
padding-right: .6rem padding-right: .6rem
.playback-controls &:first-of-type
padding-left: .6rem padding-left: .6rem
.button-menu
svg.volume-bar
overflow: visible
.inactive
fill: $background
.active
fill: $link
.click-dummy
cursor: pointer
fill: transparent
.button-menu
position: absolute
z-index: 100
width: 36px
bottom: calc(100% + .3em)
padding: $button-padding-horizontal $button-padding-horizontal / 2
border-radius: $radius
background: $white
color: $dark
box-shadow: 0 0 2px rgba(0,0,0,.1), 0 0 4px rgba(0,0,0,.1)
// little arrow at the bottom
&::after
position: absolute
content: ''
display: block
width: 6px
height: 6px
background: inherit
top: 100%
left: 50%
margin-left: -3px
margin-top: -3px
transform: rotate(45deg)
box-shadow: 2px 2px 1px rgba(0,0,0,.1)
// preview card for album or artist listings // preview card for album or artist listings
.preview-card .preview-card
.card-content > div, .card-content > div,