aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/tubo/components/player.cljs
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/tubo/components/player.cljs')
-rw-r--r--src/frontend/tubo/components/player.cljs149
1 files changed, 90 insertions, 59 deletions
diff --git a/src/frontend/tubo/components/player.cljs b/src/frontend/tubo/components/player.cljs
index e59d3b5..0373c27 100644
--- a/src/frontend/tubo/components/player.cljs
+++ b/src/frontend/tubo/components/player.cljs
@@ -1,19 +1,22 @@
(ns tubo.components.player
(:require
+ [clojure.string :as str]
[reagent.core :as r]
[re-frame.core :as rf]
- [reagent.core :as r]
- [reagent.dom :as rdom]
["@vidstack/react" :refer (MediaPlayer MediaProvider Poster)]
- ["@vidstack/react/player/layouts/default" :refer (defaultLayoutIcons DefaultVideoLayout DefaultAudioLayout)]))
+ ["@vidstack/react/player/layouts/default" :refer
+ (defaultLayoutIcons DefaultVideoLayout DefaultAudioLayout)]))
(defn get-video-player-sources
[available-streams service-id]
(if available-streams
(if (= service-id 3)
- (map (fn [{:keys [content]}] {:src content :type "video/mp4"}) (reverse available-streams))
+ (map (fn [{:keys [content]}] {:src content :type "video/mp4"})
+ (reverse available-streams))
(->> available-streams
- (filter #(and (not= (:format %) "WEBMA_OPUS") (not= (:format %) "OPUS") (not= (:format %) "M4A")))
+ (filter #(and (not= (:format %) "WEBMA_OPUS")
+ (not= (:format %) "OPUS")
+ (not= (:format %) "M4A")))
(sort-by :bitrate)
(#(if (empty? (filter (fn [x] (= (:format x) "MP3")) %))
(reverse %)
@@ -23,28 +26,34 @@
[]))
(defn video-player
- [stream !player]
- (let [!elapsed-time @(rf/subscribe [:elapsed-time])
+ [_stream _!player]
+ (let [!elapsed-time @(rf/subscribe [:elapsed-time])
!main-player-first? (r/atom true)]
(r/create-class
{:component-will-unmount #(rf/dispatch [:main-player/ready false])
:reagent-render
- (fn [{:keys [name video-streams audio-streams thumbnail-url service-id]} !player]
+ (fn [{:keys [name video-streams audio-streams thumbnail-url service-id]}
+ !player]
(let [show-main-player? @(rf/subscribe [:main-player/show])]
[:> MediaPlayer
{:title name
- :src (get-video-player-sources (into video-streams audio-streams) service-id)
+ :src (get-video-player-sources (into video-streams
+ audio-streams)
+ service-id)
:poster thumbnail-url
:class "w-full xl:w-3/5 overflow-hidden"
:playsInline true
:ref #(reset! !player %)
- :loop (when show-main-player? (= @(rf/subscribe [:loop-playback]) :stream))
+ :loop (when show-main-player?
+ (= @(rf/subscribe [:loop-playback]) :stream))
:onSeeked (when show-main-player?
#(reset! !elapsed-time (.-currentTime @!player)))
:onTimeUpdate (when show-main-player?
#(reset! !elapsed-time (.-currentTime @!player)))
:onEnded #(when show-main-player?
- (rf/dispatch [:queue/change-pos (inc @(rf/subscribe [:queue-pos]))])
+ (rf/dispatch [:queue/change-pos
+ (inc @(rf/subscribe
+ [:queue-pos]))])
(reset! !elapsed-time 0))
:onLoadedData (fn []
(when show-main-player?
@@ -56,9 +65,10 @@
:onSourceChange #(when-not @!main-player-first?
(reset! !elapsed-time 0))}
[:> MediaProvider
- [:> Poster {:src thumbnail-url
- :alt name
- :class :vds-poster}]]
+ [:> Poster
+ {:src thumbnail-url
+ :alt name
+ :class :vds-poster}]]
[:> DefaultVideoLayout {:icons defaultLayoutIcons}]]))})))
(defn get-audio-player-sources
@@ -71,13 +81,13 @@
[]))
(defn audio-player
- [stream !player]
+ [_stream _!player]
(let [!elapsed-time @(rf/subscribe [:elapsed-time])
!bg-player-first? (r/atom nil)]
(r/create-class
- {:component-will-unmount #(rf/dispatch [:background-player/ready false])
+ {:component-will-unmount #(rf/dispatch [:bg-player/ready false])
:reagent-render
- (fn [{:keys [name audio-streams thumbnail-url]} !player]
+ (fn [{:keys [name audio-streams]} !player]
[:> MediaPlayer
{:title name
:class "invisible fixed"
@@ -86,19 +96,20 @@
:viewType "audio"
:ref #(reset! !player %)
:loop (= @(rf/subscribe [:loop-playback]) :stream)
- :onCanPlay #(rf/dispatch [:background-player/ready true])
+ :onCanPlay #(rf/dispatch [:bg-player/ready true])
:onSeeked #(reset! !elapsed-time (.-currentTime @!player))
:onTimeUpdate #(reset! !elapsed-time (.-currentTime @!player))
:onEnded (fn []
- (rf/dispatch [:queue/change-pos (inc @(rf/subscribe [:queue-pos]))])
+ (rf/dispatch [:queue/change-pos
+ (inc @(rf/subscribe [:queue-pos]))])
(reset! !elapsed-time 0))
- :onPlay #(rf/dispatch [:background-player/play])
+ :onPlay #(rf/dispatch [:bg-player/play])
:onReplay (fn []
- (rf/dispatch [:background-player/set-paused false])
+ (rf/dispatch [:bg-player/set-paused false])
(reset! !elapsed-time 0))
- :onPause #(rf/dispatch [:background-player/set-paused true])
+ :onPause #(rf/dispatch [:bg-player/set-paused true])
:onLoadedData (fn []
- (rf/dispatch [:background-player/start])
+ (rf/dispatch [:bg-player/start])
(when-not @!bg-player-first?
(reset! !bg-player-first? true)))
:onSourceChange #(when @!bg-player-first?
@@ -107,7 +118,8 @@
[:> DefaultAudioLayout {:icons defaultLayoutIcons}]])})))
(defonce base-slider-classes
- ["h-2" "cursor-pointer" "appearance-none" "bg-neutral-300" "dark:bg-neutral-600"
+ ["h-2" "cursor-pointer" "appearance-none" "bg-neutral-300"
+ "dark:bg-neutral-600"
"rounded-full" "overflow-hidden" "focus:outline-none"
"[&::-webkit-slider-thumb]:appearance-none"
"[&::-webkit-slider-thumb]:border-0"
@@ -124,34 +136,50 @@
(defn get-slider-shadow-classes
[service-color]
(case service-color
- "#cc0000" ["[&::-webkit-slider-thumb]:shadow-[#cc0000]" "[&::-moz-range-thumb]:shadow-[#cc0000]"]
- "#ff7700" ["[&::-webkit-slider-thumb]:shadow-[#ff7700]" "[&::-moz-range-thumb]:shadow-[#ff7700]"]
- "#333333" ["[&::-webkit-slider-thumb]:shadow-[#333333]" "[&::-moz-range-thumb]:shadow-[#333333]"]
- "#F2690D" ["[&::-webkit-slider-thumb]:shadow-[#F2690D]" "[&::-moz-range-thumb]:shadow-[#F2690D]"]
- "#629aa9" ["[&::-webkit-slider-thumb]:shadow-[#629aa9]" "[&::-moz-range-thumb]:shadow-[#629aa9]"]
- ["[&::-webkit-slider-thumb]:shadow-neutral-300" "[&::-moz-range-thumb]:shadow-neutral-300"]))
+ "#cc0000" ["[&::-webkit-slider-thumb]:shadow-[#cc0000]"
+ "[&::-moz-range-thumb]:shadow-[#cc0000]"]
+ "#ff7700" ["[&::-webkit-slider-thumb]:shadow-[#ff7700]"
+ "[&::-moz-range-thumb]:shadow-[#ff7700]"]
+ "#333333" ["[&::-webkit-slider-thumb]:shadow-[#333333]"
+ "[&::-moz-range-thumb]:shadow-[#333333]"]
+ "#F2690D" ["[&::-webkit-slider-thumb]:shadow-[#F2690D]"
+ "[&::-moz-range-thumb]:shadow-[#F2690D]"]
+ "#629aa9" ["[&::-webkit-slider-thumb]:shadow-[#629aa9]"
+ "[&::-moz-range-thumb]:shadow-[#629aa9]"]
+ ["[&::-webkit-slider-thumb]:shadow-neutral-300"
+ "[&::-moz-range-thumb]:shadow-neutral-300"]))
(defn get-slider-bg-classes
[service-color]
(case service-color
- "#cc0000" ["[&::-webkit-slider-thumb]:bg-[#cc0000]" "[&::-moz-range-thumb]:bg-[#cc0000]"]
- "#ff7700" ["[&::-webkit-slider-thumb]:bg-[#ff7700]" "[&::-moz-range-thumb]:bg-[#ff7700]"]
- "#333333" ["[&::-webkit-slider-thumb]:bg-[#333333]" "[&::-moz-range-thumb]:bg-[#333333]"]
- "#F2690D" ["[&::-webkit-slider-thumb]:bg-[#F2690D]" "[&::-moz-range-thumb]:bg-[#F2690D]"]
- "#629aa9" ["[&::-webkit-slider-thumb]:bg-[#629aa9]" "[&::-moz-range-thumb]:bg-[#629aa9]"]
- ["[&::-webkit-slider-thumb]:bg-neutral-300" "[&::-moz-range-thumb]:bg-neutral-300"]))
+ "#cc0000" ["[&::-webkit-slider-thumb]:bg-[#cc0000]"
+ "[&::-moz-range-thumb]:bg-[#cc0000]"]
+ "#ff7700" ["[&::-webkit-slider-thumb]:bg-[#ff7700]"
+ "[&::-moz-range-thumb]:bg-[#ff7700]"]
+ "#333333" ["[&::-webkit-slider-thumb]:bg-[#333333]"
+ "[&::-moz-range-thumb]:bg-[#333333]"]
+ "#F2690D" ["[&::-webkit-slider-thumb]:bg-[#F2690D]"
+ "[&::-moz-range-thumb]:bg-[#F2690D]"]
+ "#629aa9" ["[&::-webkit-slider-thumb]:bg-[#629aa9]"
+ "[&::-moz-range-thumb]:bg-[#629aa9]"]
+ ["[&::-webkit-slider-thumb]:bg-neutral-300"
+ "[&::-moz-range-thumb]:bg-neutral-300"]))
-(defn time-slider [!player !elapsed-time service-color]
- (let [styles (concat base-slider-classes
- (get-slider-bg-classes service-color)
- (get-slider-shadow-classes service-color))
- bg-player-ready? @(rf/subscribe [:background-player/ready])]
+(defn time-slider
+ [!player !elapsed-time service-color]
+ (let [styles (concat base-slider-classes
+ (get-slider-bg-classes service-color)
+ (get-slider-shadow-classes service-color))
+ bg-player-ready? @(rf/subscribe [:bg-player/ready])]
[:input.w-full
{:class styles
:type "range"
:on-input #(reset! !elapsed-time (.. % -target -value))
- :on-change #(when (and bg-player-ready? @!player) (set! (.-currentTime @!player) @!elapsed-time))
- :max (if (and bg-player-ready? @!player (not (js/isNaN (.-duration @!player))))
+ :on-change #(when (and bg-player-ready? @!player)
+ (set! (.-currentTime @!player) @!elapsed-time))
+ :max (if (and bg-player-ready?
+ @!player
+ (not (js/isNaN (.-duration @!player))))
(.floor js/Math (.-duration @!player))
100)
:value @!elapsed-time}]))
@@ -159,29 +187,30 @@
(defn button
[& {:keys [icon on-click disabled? show-on-mobile? extra-classes]}]
[:button.outline-none.focus:ring-transparent.px-2.pt-1
- {:class (into (into (when disabled? [:opacity-50 :cursor-auto])
- (when-not show-on-mobile? [:hidden :lg:block]))
- extra-classes)
+ {:class (into (into (when disabled? [:opacity-50 :cursor-auto])
+ (when-not show-on-mobile? [:hidden :lg:block]))
+ extra-classes)
:on-click on-click}
icon])
(defn loop-button
[loop-playback color show-on-mobile?]
[button
- :icon [:div.relative.flex.items-center
- [:i.fa-solid.fa-repeat
- {:style {:color (when loop-playback color)}}]
- (when (= loop-playback :stream)
- [:div.absolute.w-full.h-full.flex.justify-center.items-center.font-bold
- {:class "text-[6px]"
- :style {:color (when loop-playback color)}}
- "1"])]
+ :icon
+ [:div.relative.flex.items-center
+ [:i.fa-solid.fa-repeat
+ {:style {:color (when loop-playback color)}}]
+ (when (= loop-playback :stream)
+ [:div.absolute.w-full.h-full.flex.justify-center.items-center.font-bold
+ {:class "text-[6px]"
+ :style {:color (when loop-playback color)}}
+ "1"])]
:on-click #(rf/dispatch [:player/loop])
:extra-classes [:text-sm]
:show-on-mobile? show-on-mobile?])
(defn volume-slider
- [player volume-level muted? service-color]
+ [_player _volume-level _muted? _service-color]
(let [show-slider? (r/atom nil)]
(fn [player volume-level muted? service-color]
(let [styles (concat ["rotate-[270deg]"]
@@ -192,13 +221,15 @@
{:on-mouse-over #(reset! show-slider? true)
:on-mouse-out #(reset! show-slider? false)}
[button
- :icon (if muted? [:i.fa-solid.fa-volume-xmark] [:i.fa-solid.fa-volume-low])
- :on-click #(rf/dispatch [:background-player/mute (not muted?) player])
+ :icon
+ (if muted? [:i.fa-solid.fa-volume-xmark] [:i.fa-solid.fa-volume-low])
+ :on-click #(rf/dispatch [:bg-player/mute (not muted?) player])
:extra-classes [:pl-3 :pr-2]]
(when @show-slider?
[:input.absolute.w-24.ml-2.m-1.bottom-16
- {:class (clojure.string/join " " styles)
+ {:class (str/join " " styles)
:type "range"
- :on-input #(rf/dispatch [:player/change-volume (.. % -target -value) player])
+ :on-input #(rf/dispatch [:player/change-volume
+ (.. % -target -value) player])
:max 100
:value volume-level}])]))))