aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Ángel Moreno <mail@migalmoreno.com>2024-12-01 13:20:15 +0100
committerMiguel Ángel Moreno <mail@migalmoreno.com>2024-12-01 13:26:44 +0100
commit0efab725aa38fc8a2072d41c50801a7df9771a41 (patch)
tree2503586145299cfd07585e8fdd17a8e97a81b623
parent04861769d80fb0d30eb3141fb67f9082f4e7bcac (diff)
feat: add tabs component for stream metadata
-rw-r--r--src/frontend/tubo/comments/views.cljs40
-rw-r--r--src/frontend/tubo/layout/views.cljs21
-rw-r--r--src/frontend/tubo/main_player/views.cljs2
-rw-r--r--src/frontend/tubo/stream/views.cljs137
4 files changed, 124 insertions, 76 deletions
diff --git a/src/frontend/tubo/comments/views.cljs b/src/frontend/tubo/comments/views.cljs
index 2b1bf7f..b148f46 100644
--- a/src/frontend/tubo/comments/views.cljs
+++ b/src/frontend/tubo/comments/views.cljs
@@ -70,24 +70,28 @@
{:keys [uploader-name uploader-avatar url]}]
(let [pagination-loading? @(rf/subscribe [:show-pagination-loading])
service-color @(rf/subscribe [:service-color])]
- [:div.flex.flex-col
- [:div
- (for [[i {:keys [replies show-replies] :as comment}]
- (map-indexed vector comments)]
- [:div.flex.flex-col {:key i}
- [:div.flex
- [comment-item
- (assoc comment
- :author-name uploader-name
- :author-avatar uploader-avatar)]]
- (when (and replies show-replies)
- [:div {:style {:marginLeft "32px"}}
- (for [[i reply] (map-indexed vector (:items replies))]
- ^{:key i}
- [comment-item
- (assoc reply
- :author-name uploader-name
- :author-avatar uploader-avatar)])])])]
+ [:div.flex.flex-col.py-4
+ (if (empty? comments)
+ [:div.flex.items-center.flex-auto.flex-col.justify-center.gap-y-4.h-44
+ [:i.fa-solid.fa-ghost.text-3xl]
+ [:p.text-lg "No available comments"]]
+ [:div
+ (for [[i {:keys [replies show-replies] :as comment}]
+ (map-indexed vector comments)]
+ [:div.flex.flex-col {:key i}
+ [:div.flex
+ [comment-item
+ (assoc comment
+ :author-name uploader-name
+ :author-avatar uploader-avatar)]]
+ (when (and replies show-replies)
+ [:div {:style {:marginLeft "32px"}}
+ (for [[i reply] (map-indexed vector (:items replies))]
+ ^{:key i}
+ [comment-item
+ (assoc reply
+ :author-name uploader-name
+ :author-avatar uploader-avatar)])])])])
(when (:url next-page)
(if pagination-loading?
[layout/loading-icon service-color]
diff --git a/src/frontend/tubo/layout/views.cljs b/src/frontend/tubo/layout/views.cljs
index d50c066..f088eef 100644
--- a/src/frontend/tubo/layout/views.cljs
+++ b/src/frontend/tubo/layout/views.cljs
@@ -236,3 +236,24 @@
[:div.flex.justify-center.gap-x-6
[primary-button "Go Back" #(rf/dispatch [:navigation/history-go -1])]
[secondary-button "Retry" #(rf/dispatch cb)]]]])
+
+(defn tabs
+ [tabs]
+ (let [!current (r/atom (nth tabs 0))]
+ (fn [tabs & {:keys [on-change]}]
+ [:div
+ (into
+ [:ul.w-full.flex.justify-center.items-center]
+ (for [[i tab] (map-indexed vector tabs)]
+ (let [selected? (= (:id tab) (:id @!current))]
+ (when tab
+ [:li.flex-auto.flex.justify-center.items-center.font-semibold.border-b-2.border-transparent
+ {:class (if selected? :border-white :border-transparent) :key i}
+ [:button.flex-auto.py-4
+ {:on-click (when (not selected?)
+ (fn []
+ (reset! !current tab)
+ (on-change (:id @!current))))}
+ (if (:label-fn tab)
+ ((:label-fn tab) (:label tab))
+ (:label tab))]]))))])))
diff --git a/src/frontend/tubo/main_player/views.cljs b/src/frontend/tubo/main_player/views.cljs
index be4c223..a06164a 100644
--- a/src/frontend/tubo/main_player/views.cljs
+++ b/src/frontend/tubo/main_player/views.cljs
@@ -30,4 +30,4 @@
[stream/metadata stream]
[stream/description stream]
[stream/comments stream]
- [stream/suggested stream]]])]))
+ [stream/related-items stream]]])]))
diff --git a/src/frontend/tubo/stream/views.cljs b/src/frontend/tubo/stream/views.cljs
index c78cfc9..51896f0 100644
--- a/src/frontend/tubo/stream/views.cljs
+++ b/src/frontend/tubo/stream/views.cljs
@@ -79,80 +79,103 @@
(defn metadata
[{:keys [name] :as stream}]
[:<>
- [:div.flex.items-center.justify-between.my-3
+ [:div.flex.items-center.justify-between.mt-3
[:h1.text-lg.sm:text-2xl.font-bold.line-clamp-1 {:title name} name]
[:div.hidden.lg:block
[metadata-popover stream]]]
- [:div.flex.justify-between.py-2.flex-nowrap
+ [:div.flex.justify-between.py-6.flex-nowrap
[metadata-uploader stream]
[metadata-stats stream]]])
(defn description
- [{:keys [description show-description]}]
+ [{:keys [description show-description tags]}]
(let [show? (:show-description @(rf/subscribe [:settings]))]
(when (and show? (seq description))
- [layout/show-more-container show-description description
- #(rf/dispatch [(if @(rf/subscribe [:main-player/show])
- :main-player/toggle-layout
- :stream/toggle-layout)
- :show-description])])))
+ [:div
+ [layout/show-more-container show-description description
+ #(rf/dispatch [(if @(rf/subscribe [:main-player/show])
+ :main-player/toggle-layout
+ :stream/toggle-layout)
+ :show-description])]
+ [:div.flex.gap-2.py-2
+ (for [[i tag] (map-indexed vector tags)]
+ ^{:key i}
+ [:span.bg-neutral-300.dark:bg-neutral-800.rounded-md.p-2.text-sm
+ (str "#" tag)])]])))
(defn comments
- [{:keys [comments-page show-comments show-comments-loading url] :as stream}]
+ [{:keys [comments-page show-comments show-comments-loading] :as stream}]
(let [show? (:show-comments @(rf/subscribe [:settings]))
service-color @(rf/subscribe [:service-color])]
- (when (and comments-page (seq (:comments comments-page)) show?)
- [layout/accordeon
- {:label "Comments"
- :on-open #(if show-comments
- (rf/dispatch [:stream/toggle-layout :show-comments])
- (if comments-page
- (rf/dispatch [:stream/toggle-layout :show-comments])
- (rf/dispatch [:comments/fetch-page url])))
- :open? show-comments
- :left-icon "fa-solid fa-comments"}
- (if show-comments-loading
- [layout/loading-icon service-color "text-2xl"]
- (when (and show-comments comments-page)
- [comments/comments comments-page stream]))])))
+ (when show?
+ (if show-comments-loading
+ [layout/loading-icon service-color "text-2xl"]
+ (when (and show-comments comments-page)
+ [comments/comments comments-page stream])))))
-(defn suggested
+(defn related-items
[_]
- (let [!menu-active? (r/atom nil)]
- (fn [{:keys [related-streams show-related]}]
+ (let [!menu-active? (r/atom nil)
+ !layout (r/atom :list)]
+ (fn [{:keys [related-streams]}]
(let [show? (:show-related @(rf/subscribe [:settings]))]
(when (and show? (seq related-streams))
- [layout/accordeon
- {:label "Suggested"
- :on-open #(rf/dispatch [(if @(rf/subscribe [:main-player/show])
- :main-player/toggle-layout
- :stream/toggle-layout)
- :show-related])
- :open? (not show-related)
- :left-icon "fa-solid fa-list"
- :right-button [layout/popover-menu !menu-active?
- [{:label "Add to queue"
- :icon [:i.fa-solid.fa-headphones]
- :on-click #(rf/dispatch [:queue/add-n
- related-streams true])}
- {:label "Add to playlist"
- :icon [:i.fa-solid.fa-plus]
- :on-click #(rf/dispatch [:modals/open
- [modals/add-to-bookmark
- related-streams]])}]]}
- [items/related-streams related-streams nil]])))))
+ [:div
+ [:div.flex.flex-wrap.items-center.justify-between.mt-8.min-w-full
+ [:div.flex.gap-2.items-center
+ [:span.font-semibold.text-xl "Next Up"]]
+ [:div.flex.gap-4
+ [layout/popover-menu !menu-active?
+ [{:label "Add to queue"
+ :icon [:i.fa-solid.fa-headphones]
+ :on-click #(rf/dispatch [:queue/add-n
+ related-streams
+ true])}
+ {:label "Add to playlist"
+ :icon [:i.fa-solid.fa-plus]
+ :on-click #(rf/dispatch [:modals/open
+ [modals/add-to-bookmark
+ related-streams]])}]]
+ [items/layout-switcher !layout]]
+ [items/related-streams related-streams nil !layout]]])))))
(defn stream
[]
- (let [stream @(rf/subscribe [:stream])
- !player @(rf/subscribe [:main-player])
- page-loading? @(rf/subscribe [:show-page-loading])]
- [:<>
- (when-not page-loading?
- [:div.flex.flex-col.justify-center.items-center.xl:pt-4
- [player/video-player stream !player]])
- [layout/content-container
- [metadata stream]
- [description stream]
- [comments stream]
- [suggested stream]]]))
+ (let [!active-tab (r/atom :comments)]
+ (fn []
+ (let [stream @(rf/subscribe [:stream])
+ !player @(rf/subscribe [:main-player])
+ page-loading? @(rf/subscribe [:show-page-loading])
+ comments-length (-> stream
+ :comments-page
+ :comments
+ count)]
+ [:<>
+ (when-not page-loading?
+ [:div.flex.flex-col.justify-center.items-center.xl:pt-4
+ [player/video-player stream !player]])
+ [layout/content-container
+ [metadata stream]
+ [description stream]
+ [:div.mt-10
+ [layout/tabs
+ [{:id :comments
+ :label "Comments"
+ :label-fn (fn [label]
+ [:div.flex.gap-3.items-center.justify-center
+ [:i.fa-solid.fa-comments]
+ [:span label]
+ [:span.dark:bg-neutral-800.rounded.px-2
+ comments-length]])}
+ {:id :related-items
+ :label "Related Items"
+ :label-fn (fn [label]
+ [:div.flex.gap-3.items-center.justify-center
+ [:i.fa-solid.fa-table-list]
+ [:span label]])}]
+ :selected-id @!active-tab
+ :on-change #(reset! !active-tab %)]]
+ (case @!active-tab
+ :comments [comments stream]
+ :related-items [related-items stream]
+ [comments stream])]]))))