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.cljs244
1 files changed, 0 insertions, 244 deletions
diff --git a/src/frontend/tubo/components/player.cljs b/src/frontend/tubo/components/player.cljs
deleted file mode 100644
index a8f3a18..0000000
--- a/src/frontend/tubo/components/player.cljs
+++ /dev/null
@@ -1,244 +0,0 @@
-(ns tubo.components.player
- (:require
- [clojure.string :as str]
- [reagent.core :as r]
- [re-frame.core :as rf]
- ["@vidstack/react" :refer (MediaPlayer MediaProvider Poster)]
- ["@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))
- (->> available-streams
- (filter #(and (not= (:format %) "WEBMA_OPUS")
- (not= (:format %) "OPUS")
- (not= (:format %) "M4A")))
- (sort-by :bitrate)
- (#(if (empty? (filter (fn [x] (= (:format x) "MP3")) %))
- (reverse %)
- %))
- (map (fn [{:keys [content]}] {:src content :type "video/mp4"}))
- first))
- []))
-
-(defn video-player
- [_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]
- (let [show-main-player? @(rf/subscribe [:main-player/show])]
- [:> MediaPlayer
- {:title name
- :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))
- :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]))])
- (reset! !elapsed-time 0))
- :onLoadedData (fn []
- (when show-main-player?
- (rf/dispatch [:main-player/start]))
- (when (and @!main-player-first? show-main-player?)
- (reset! !main-player-first? false)))
- :onPlay #(rf/dispatch [:main-player/play])
- :onCanPlay #(rf/dispatch [:main-player/ready true])
- :onSourceChange #(when-not @!main-player-first?
- (reset! !elapsed-time 0))}
- [:> MediaProvider
- [:> Poster
- {:src thumbnail-url
- :alt name
- :class :vds-poster}]]
- [:> DefaultVideoLayout {:icons defaultLayoutIcons}]]))})))
-
-(defn get-audio-player-sources
- [available-streams]
- (if available-streams
- (->> available-streams
- (filter #(not= (:format %) "OPUS"))
- (sort-by :bitrate)
- (map (fn [{:keys [content]}] {:src content :type "video/mp4"})))
- []))
-
-(defn audio-player
- [_stream _!player]
- (let [!elapsed-time @(rf/subscribe [:elapsed-time])
- !bg-player-first? (r/atom nil)]
- (r/create-class
- {:component-will-unmount #(rf/dispatch [:bg-player/ready false])
- :reagent-render
- (fn [{:keys [name audio-streams]} !player]
- [:> MediaPlayer
- {:title name
- :class "invisible fixed"
- :controls []
- :src (get-audio-player-sources audio-streams)
- :viewType "audio"
- :ref #(reset! !player %)
- :loop (= @(rf/subscribe [:loop-playback]) :stream)
- :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]))])
- (reset! !elapsed-time 0))
- :onPlay #(rf/dispatch [:bg-player/play])
- :onReplay (fn []
- (rf/dispatch [:bg-player/set-paused false])
- (reset! !elapsed-time 0))
- :onPause #(rf/dispatch [:bg-player/set-paused true])
- :onLoadedData (fn []
- (rf/dispatch [:bg-player/start])
- (when-not @!bg-player-first?
- (reset! !bg-player-first? true)))
- :onSourceChange #(when @!bg-player-first?
- (reset! !elapsed-time 0))}
- [:> MediaProvider]
- [:> DefaultAudioLayout {:icons defaultLayoutIcons}]])})))
-
-(defonce base-slider-classes
- ["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"
- "[&::-webkit-slider-thumb]:rounded-full"
- "[&::-webkit-slider-thumb]:h-2"
- "[&::-webkit-slider-thumb]:w-2"
- "[&::-webkit-slider-thumb]:shadow-[-405px_0_0_400px]"
- "[&::-moz-range-thumb]:border-0"
- "[&::-moz-range-thumb]:rounded-full"
- "[&::-moz-range-thumb]:h-2"
- "[&::-moz-range-thumb]:w-2"
- "[&::-moz-range-thumb]:shadow-[-405px_0_0_400px]"])
-
-(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"]))
-
-(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"]))
-
-(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))))
- (.floor js/Math (.-duration @!player))
- 100)
- :value @!elapsed-time}]))
-
-(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)
- :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"])]
- :on-click #(rf/dispatch [:player/loop])
- :extra-classes [:text-sm]
- :show-on-mobile? show-on-mobile?])
-
-(defn shuffle-button
- [shuffle? color show-on-mobile?]
- [button
- :icon
- [:i.fa-solid.fa-shuffle {:style {:color (when shuffle? color)}}]
- :on-click #(rf/dispatch [:queue/shuffle (not shuffle?)])
- :extra-classes [:text-sm]
- :show-on-mobile? show-on-mobile?])
-
-(defn volume-slider
- [_player _volume-level _muted? _service-color]
- (let [show-slider? (r/atom nil)]
- (fn [player volume-level muted? service-color]
- (let [styles (concat ["rotate-[270deg]"]
- base-slider-classes
- (get-slider-bg-classes service-color)
- (get-slider-shadow-classes service-color))]
- [:div.relative.flex.flex-col.justify-center.items-center
- {: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 [: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 (str/join " " styles)
- :type "range"
- :on-input #(rf/dispatch [:player/change-volume
- (.. % -target -value) player])
- :max 100
- :value volume-level}])]))))