aboutsummaryrefslogtreecommitdiff
path: root/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/tubo/components/video_player.cljs46
-rw-r--r--src/frontend/tubo/events.cljs18
-rw-r--r--src/frontend/tubo/subs.cljs5
-rw-r--r--src/frontend/tubo/views/stream.cljs94
4 files changed, 79 insertions, 84 deletions
diff --git a/src/frontend/tubo/components/video_player.cljs b/src/frontend/tubo/components/video_player.cljs
index c94579a..1825f50 100644
--- a/src/frontend/tubo/components/video_player.cljs
+++ b/src/frontend/tubo/components/video_player.cljs
@@ -1,27 +1,39 @@
(ns tubo.components.video-player
(:require
+ [re-frame.core :as rf]
[reagent.core :as r]
[reagent.dom :as rdom]
- ["video.js" :as videojs]))
+ ["video.js" :as videojs]
+ ["videojs-mobile-ui"]
+ ["@silvermine/videojs-quality-selector" :as VideojsQualitySelector]))
(defn player
- [options url]
- (let [!player (atom nil)]
+ [options]
+ (let [!player (atom nil)
+ service-color @(rf/subscribe [:service-color])
+ {:keys [theme]} @(rf/subscribe [:settings])]
(r/create-class
{:display-name "VideoPlayer"
:component-did-mount
- (fn [this]
- (reset! !player (videojs (rdom/dom-node this) (clj->js options))))
- :component-did-update
- (fn [this [_ prev-argv prev-more]]
- (when (and @!player (not= prev-more (first (r/children this))))
- (.src @!player (apply array (map #(js-obj "type" % "src" (first (r/children this)))
- (map #(get % "type") (get options "sources")))))
- (.ready @!player #(.play @!player))))
- :component-will-unmount
- (fn [_]
- (when @!player
- (.dispose @!player)))
+ (fn [^videojs/VideoJsPlayer this]
+ (let [set-bg-color! #(set! (.. (.$ (.getChild ^videojs/VideoJsPlayer @!player "ControlBar") %)
+ -style
+ -background)
+ service-color)]
+ (VideojsQualitySelector videojs)
+ (reset! !player (videojs (rdom/dom-node this) (clj->js options)))
+ (set-bg-color! ".vjs-play-progress")
+ (set-bg-color! ".vjs-volume-level")
+ (set-bg-color! ".vjs-slider-bar")
+ (.ready @!player #(.mobileUi ^videojs/VideoJsPlayer @!player))
+ (.on @!player "play" (fn []
+ (.audioPosterMode
+ @!player
+ (clojure.string/includes?
+ (:label (first (filter #(= (:src %) (.src @!player))
+ (:sources options))))
+ "audio-only"))))))
+ :component-will-unmount #(when @!player (.dispose @!player))
:reagent-render
- (fn [options url]
- [:video-js.vjs-default-skin.vjs-big-play-centered.bottom-0.object-cover.min-h-full.max-h-full.min-w-full.focus:ring-transparent])})))
+ (fn [options]
+ [:video-js.vjs-tubo.vjs-default-skin.vjs-big-play-centered.vjs-show-big-play-button-on-pause])})))
diff --git a/src/frontend/tubo/events.cljs b/src/frontend/tubo/events.cljs
index 90282ed..a7d5269 100644
--- a/src/frontend/tubo/events.cljs
+++ b/src/frontend/tubo/events.cljs
@@ -621,20 +621,10 @@
(rf/reg-event-fx
::get-stream-page
(fn [{:keys [db]} [_ uri]]
- {:db (assoc db :show-page-loading true)
- :fx [[:dispatch [::fetch-stream-page uri]]]}))
-
-(rf/reg-event-db
- ::change-stream-format
- (fn [{:keys [stream] :as db} [_ format-id]]
- (let [{:keys [audio-streams video-streams]} stream]
- (if format-id
- (assoc db :stream-format
- (first (filter #(= format-id (:id %))
- (apply conj audio-streams video-streams))))
- (assoc db :stream-format (if (empty? video-streams)
- (first audio-streams)
- (last video-streams)))))))
+ (assoc
+ (api/get-request (str "/api/streams/" (js/encodeURIComponent uri))
+ [::load-stream-page] [::bad-response])
+ :db (assoc db :show-page-loading true))))
(rf/reg-event-fx
::load-channel
diff --git a/src/frontend/tubo/subs.cljs b/src/frontend/tubo/subs.cljs
index 0ca48f0..d30d69c 100644
--- a/src/frontend/tubo/subs.cljs
+++ b/src/frontend/tubo/subs.cljs
@@ -71,11 +71,6 @@
(:stream db)))
(rf/reg-sub
- :stream-format
- (fn [db _]
- (:stream-format db)))
-
-(rf/reg-sub
:playlist
(fn [db _]
(:playlist db)))
diff --git a/src/frontend/tubo/views/stream.cljs b/src/frontend/tubo/views/stream.cljs
index b609511..3b97f42 100644
--- a/src/frontend/tubo/views/stream.cljs
+++ b/src/frontend/tubo/views/stream.cljs
@@ -17,59 +17,57 @@
uploader-url upload-date related-streams
thumbnail-url show-comments-loading comments-page
show-comments show-related show-description service-id]
- :as stream} @(rf/subscribe [:stream])
- {show-comments? :show-comments show-related? :show-related
- show-description? :show-description} @(rf/subscribe [:settings])
+ :as stream} @(rf/subscribe [:stream])
+ {show-comments? :show-comments
+ show-related? :show-related
+ show-description? :show-description}
+ @(rf/subscribe [:settings])
available-streams (apply conj audio-streams video-streams)
- {:keys [content id] :as stream-format} @(rf/subscribe [:stream-format])
- page-loading? @(rf/subscribe [:show-page-loading])
- service-color @(rf/subscribe [:service-color])
- bookmarks @(rf/subscribe [:bookmarks])]
+ page-loading? @(rf/subscribe [:show-page-loading])
+ service-color @(rf/subscribe [:service-color])
+ bookmarks @(rf/subscribe [:bookmarks])
+ sources (reverse (map (fn [{:keys [content format resolution averageBitrate]}]
+ {:src content
+ :type "video/mp4"
+ :label (str (or resolution "audio-only") " "
+ format
+ (when-not resolution
+ (str " " averageBitrate "kbit/s")))})
+ available-streams))
+ player-elements ["playToggle" "progressControl"
+ "volumePanel" "playbackRateMenuButton"
+ "QualitySelector" "fullscreenToggle"]]
[layout/content-container
[:div.flex.justify-center.relative
{:class "h-[300px] md:h-[450px] lg:h-[600px]"}
- (when stream-format
- [player/player {"sources" [{"src" content "type" "video/mp4"}
- {"src" content "type" "video/webm"}]
- "poster" thumbnail-url
- "controls" true
- "responsive" true
- "fill" true}
- content])]
- [:div.overflow-x-hidden
- [:div.flex.flex.w-full.my-4.justify-center
- [:button.sm:px-2.py-1.text-sm.sm:text-base.text-neutral-600.dark:text-neutral-300
- {:on-click #(rf/dispatch [::events/switch-to-audio-player stream service-color])}
- [:i.fa-solid.fa-headphones]
- [:span.mx-3 "Background"]]
- (if (some #(= (:url %) url) bookmarks)
- [:button.sm:px-2.py-1.text-sm.sm:text-base.text-neutral-600.dark:text-neutral-300
- {:on-click #(rf/dispatch [::events/remove-from-bookmarks stream])}
- [:i.fa-solid.fa-bookmark]
- [:span.mx-3 "Bookmarked"]]
- [:button.sm:px-2.py-1.text-sm.sm:text-base.text-neutral-600.dark:text-neutral-300
- {:on-click #(rf/dispatch [::events/add-to-bookmarks stream])}
- [:i.fa-regular.fa-bookmark]
- [:span.mx-3 "Bookmark"]])
- [:button.sm:px-2.py-1.text-sm.sm:text-base.text-neutral-600.dark:text-neutral-300
- [:a.block.sm:inline-block {:href url}
- [:i.fa-solid.fa-external-link-alt]
- [:span.mx-3 "Original"]]]
- (when stream-format
- [:div.relative.flex.flex-col.items-center.justify-center.text-neutral-600.dark:text-neutral-300
- [:select.border-none.focus:ring-transparent.dark:bg-blend-color-dodge.pr-8.w-full.text-ellipsis.text-sm.sm:text-base
- {:on-change #(rf/dispatch [::events/change-stream-format (.. % -target -value)])
- :value id
- :style {:background "transparent"}}
- (when available-streams
- (for [[i {:keys [id format resolution averageBitrate]}] (map-indexed vector available-streams)]
- [:option.dark:bg-neutral-900.border-none {:value id :key i}
- (str (or resolution "audio-only") " " format (when-not resolution (str " " averageBitrate "kbit/s")))]))]
- [:div.flex.absolute.min-h-full.top-0.right-4.items-center.justify-end
- [:i.fa-solid.fa-caret-down]]])]
+ [player/player
+ {:sources sources
+ :poster thumbnail-url
+ :controls true
+ :controlBar {:children player-elements}
+ :preload "metadata"
+ :responsive true
+ :fill true
+ :playbackRates [0.5 1 1.5 2]}]]
+ [:div
[:div.flex.flex-col
- [:div.min-w-full.pb-3
- [:h1.text-2xl.font-extrabold.line-clamp-1 name]]
+ [:div.flex.items-center.justify-between.pt-4
+ [:div.flex-auto
+ [:h1.text-lg.sm:text-2xl.font-extrabold.line-clamp-1 name]]
+ [:div.flex.flex-auto.justify-end.items-center.my-3.gap-x-5
+ [:button
+ {:on-click #(rf/dispatch [::events/switch-to-audio-player stream service-color])}
+ [:i.fa-solid.fa-headphones]]
+ [:button
+ [:a.block.sm:inline-block {:href url :target "__blank"}
+ [:i.fa-solid.fa-external-link-alt]]]
+ (if (some #(= (:url %) url) bookmarks)
+ [:button
+ {:on-click #(rf/dispatch [::events/remove-from-bookmarks stream])}
+ [:i.fa-solid.fa-bookmark {:style {:color service-color}}]]
+ [:button
+ {:on-click #(rf/dispatch [::events/add-to-bookmarks stream])}
+ [:i.fa-regular.fa-bookmark]])]]
[:div.flex.justify-between.py-2.flex-nowrap
[:div.flex.items-center
[layout/uploader-avatar uploader-avatar uploader-name