diff options
author | Miguel Ángel Moreno <mail@migalmoreno.com> | 2023-10-30 00:55:27 +0100 |
---|---|---|
committer | Miguel Ángel Moreno <mail@migalmoreno.com> | 2023-10-30 00:55:27 +0100 |
commit | e9b089fce0394ce2e9ab7997a079bc22374e235a (patch) | |
tree | 494ae752f9a9164a2ed218563c6927d8dc60ea7f | |
parent | bcd3d52bf9f5da7bdd5f449515334816feff542f (diff) |
feat(frontend): add stream playback events
-rw-r--r-- | src/frontend/tubo/components/audio_player.cljs | 29 | ||||
-rw-r--r-- | src/frontend/tubo/events.cljs | 45 | ||||
-rw-r--r-- | src/frontend/tubo/subs.cljs | 14 |
3 files changed, 69 insertions, 19 deletions
diff --git a/src/frontend/tubo/components/audio_player.cljs b/src/frontend/tubo/components/audio_player.cljs index f4945c8..7cc5fb1 100644 --- a/src/frontend/tubo/components/audio_player.cljs +++ b/src/frontend/tubo/components/audio_player.cljs @@ -9,8 +9,7 @@ (defn player [] - (let [!autoplay? (r/atom true) - !volume-level (r/atom 100)] + (let [!autoplay? (r/atom true)] (fn [] (let [media-queue @(rf/subscribe [:media-queue]) media-queue-pos @(rf/subscribe [:media-queue-pos]) @@ -22,16 +21,18 @@ is-window-visible @(rf/subscribe [:is-window-visible]) loop-file? @(rf/subscribe [:loop-file]) loop-playlist? @(rf/subscribe [:loop-playlist]) + volume-level @(rf/subscribe [:volume-level]) + muted? @(rf/subscribe [:muted]) !elapsed-time @(rf/subscribe [:elapsed-time]) !player @(rf/subscribe [:player])] (when show-audio-player? - [:div.sticky.bottom-0.z-40.bg-white.dark:bg-neutral-900.px-3.py-5.sm:p-5.absolute.box-border.m-0 + [:div.sticky.bottom-0.z-40.bg-white.dark:bg-neutral-900.p-3.sm:p-5.absolute.box-border.m-0 {:style {:borderTop (str "2px solid " service-color) :display (when show-media-queue? "none")}} [:div.flex.items-center.justify-between [:div.flex.items-center [:div {:style {:height "40px" :width "70px" :maxWidth "70px" :minWidth "70px"}} [:img.min-h-full.max-h-full.object-cover.min-w-full.max-w-full.w-full {:src thumbnail-url}]] - [:div.flex.flex-col.px-4 + [:div.flex.flex-col.px-2 [:a.text-xs.line-clamp-1 {:href (rfe/href :tubo.routes/stream nil {:url url})} name] [:a.text-xs.pt-2.text-neutral-600.dark:text-neutral-300.line-clamp-1 @@ -43,7 +44,7 @@ :on-time-update #(when (and @!player (> (.-readyState @!player) 0)) (reset! !elapsed-time (.-currentTime @!player))) :on-loaded-data #(when (and @!player (> (.-readyState @!player) 0)) - (.play @!player) + (rf/dispatch [::events/start-playback @!player]) (set! (.-currentTime @!player) @!elapsed-time)) :on-ended #(when (and @!player (> (.-readyState @!player) 0)) (let [idx (if (< (+ media-queue-pos 1) (count media-queue)) @@ -53,7 +54,7 @@ (reset! !elapsed-time 0) (when (and (not is-window-visible) loop-playlist?) (set! (.-src @!player) (:stream (nth media-queue idx))) - (.play @!player))))}]] + (rf/dispatch [::events/start-playback @!player]))))}]] [:div.flex [:button:focus:ring-transparent.mx-2.cursor-pointer {:on-click #(rf/dispatch [::events/toggle-media-queue])} @@ -71,10 +72,7 @@ {:on-click #(set! (.-currentTime @!player) (- @!elapsed-time 5))} [:i.fa-solid.fa-backward]] [:button.focus:outline-none.mx-2 - {:on-click #(when-let [player @!player] - (if (.-paused player) - (.play player) - (.pause player)))} + {:on-click #(rf/dispatch [::events/start-playback @!player])} (if @!player (if show-audio-player-loading? [loading/loading-icon service-color "text-1xl"] @@ -119,19 +117,16 @@ {:style {:color (when loop-playlist? service-color)}}]] [:div.hidden.ml:flex.items-center [:button.focus:outline-none.mx-2 - {:on-click #(when-let [player @!player] - (set! (.-muted player) (not (.-muted player))))} - (if (and @!player (.-muted @!player)) + {:on-click #(rf/dispatch [::events/toggle-mute @!player])} + (if (or (and @!player muted?)) [:i.fa-solid.fa-volume-xmark] [:i.fa-solid.fa-volume-low])] [:input.w-20.bg-gray-200.rounded-lg.cursor-pointer.focus:outline-none.h-1.range-sm.mx-2 {:type "range" - :on-input #(do (reset! !volume-level (.. % -target -value)) - (and @!player (> (.-readyState @!player) 0) - (set! (.-volume @!player) (/ @!volume-level 100)))) + :on-input #(rf/dispatch [::events/change-volume-level (.. % -target -value) @!player]) :style {:accentColor service-color} :max 100 - :value (if (and @!player (.-muted @!player)) 0 @!volume-level)}]]] + :value volume-level}]]] [:div.mx-2 [:i.fa-solid.fa-close.cursor-pointer {:on-click (fn [] diff --git a/src/frontend/tubo/events.cljs b/src/frontend/tubo/events.cljs index 157c509..cebd707 100644 --- a/src/frontend/tubo/events.cljs +++ b/src/frontend/tubo/events.cljs @@ -26,6 +26,8 @@ :loop-playlist (if (nil? loop-playlist) true loop-playlist) :media-queue (if (nil? media-queue) [] media-queue) :media-queue-pos (if (nil? media-queue-pos) 0 media-queue-pos) + :volume-level (if (nil? volume-level) 100 volume-level) + :muted (if (nil? muted) false muted) :current-match nil :show-audio-player (if (nil? show-audio-player) false show-audio-player) :settings @@ -55,6 +57,26 @@ (fn [_ _] {::history-back! nil})) +(rf/reg-fx + ::player-volume + (fn [{:keys [player volume]}] + (when (and player (> (.-readyState player) 0)) + (set! (.-volume player) (/ volume 100))))) + +(rf/reg-fx + ::player-mute + (fn [{:keys [player muted?]}] + (when (and player (> (.-readyState player) 0)) + (set! (.-muted player) muted?)))) + +(rf/reg-fx + ::player-playback + (fn [{:keys [player]}] + (when (and player (> (.-readyState player) 0)) + (if (.-paused player) + (.play player) + (.pause player))))) + (rf/reg-event-fx ::toggle-mobile-nav (fn [{:keys [db]} _] @@ -75,6 +97,29 @@ :store (assoc store :loop-file (not (:loop-file store)))})) (rf/reg-event-fx + ::change-volume-level + [(rf/inject-cofx :store)] + (fn [{:keys [db store]} [_ value player]] + {:db (assoc db :volume-level value) + :store (assoc store :volume-level value) + ::player-volume {:player player :volume value}})) + +(rf/reg-event-fx + ::start-playback + (fn [{:keys [db]} [_ player]] + {::player-playback {:player player} + ::player-volume {:player player :volume (:volume-level db)} + ::player-mute {:player player :muted? (:muted db)}})) + +(rf/reg-event-fx + ::toggle-mute + [(rf/inject-cofx :store)] + (fn [{:keys [db store]} [_ player]] + {:db (assoc db :muted (not (:muted db))) + :store (assoc store :muted (not (:muted store))) + ::player-mute {:player player :muted? (not (:muted db))}})) + +(rf/reg-event-fx ::toggle-loop-playlist [(rf/inject-cofx :store)] (fn [{:keys [db store]} _] diff --git a/src/frontend/tubo/subs.cljs b/src/frontend/tubo/subs.cljs index ed51d60..9f684e1 100644 --- a/src/frontend/tubo/subs.cljs +++ b/src/frontend/tubo/subs.cljs @@ -17,8 +17,8 @@ (.addEventListener js/window "touchmove" compute-scroll-distance) a)) -(def !elapsed-time (r/atom 0)) -(def !player (r/atom nil)) +(defonce !elapsed-time (r/atom 0)) +(defonce !player (r/atom nil)) (rf/reg-sub :is-window-visible @@ -41,6 +41,16 @@ !player)) (rf/reg-sub + :volume-level + (fn [db _] + (:volume-level db))) + +(rf/reg-sub + :muted + (fn [db _] + (:muted db))) + +(rf/reg-sub :http-response (fn [db _] (:http-response db))) |