From 87ae04fd02a11db1d394e647c2c868d293d196ea Mon Sep 17 00:00:00 2001 From: Miguel Ángel Moreno Date: Thu, 19 Dec 2024 02:55:47 +0100 Subject: feat: simplify popover invocations --- src/frontend/tubo/bg_player/views.cljs | 112 +++++++++++++++++---------------- src/frontend/tubo/bookmarks/subs.cljs | 28 +++++++++ src/frontend/tubo/bookmarks/views.cljs | 11 ++-- src/frontend/tubo/channel/views.cljs | 27 ++++---- src/frontend/tubo/items/views.cljs | 106 ++++++++++++++----------------- src/frontend/tubo/playlist/views.cljs | 27 ++++---- src/frontend/tubo/queue/views.cljs | 14 ++--- src/frontend/tubo/stream/views.cljs | 63 +++++++++---------- 8 files changed, 197 insertions(+), 191 deletions(-) diff --git a/src/frontend/tubo/bg_player/views.cljs b/src/frontend/tubo/bg_player/views.cljs index a7e511b..1c5d28a 100644 --- a/src/frontend/tubo/bg_player/views.cljs +++ b/src/frontend/tubo/bg_player/views.cljs @@ -203,60 +203,66 @@ (utils/format-duration (.-duration @!player)) "--:--")]]])) +(defn popover + [{:keys [uploader-url url] :as stream}] + (let [queue @(rf/subscribe [:queue]) + queue-pos @(rf/subscribe [:queue/position]) + favorited? @(rf/subscribe [:bookmarks/favorited url]) + bookmark #(rf/dispatch [:modals/open + [modals/add-to-bookmark %]])] + [layout/popover + [{:label (if favorited? "Remove favorite" "Favorite") + :icon [:i.fa-solid.fa-heart + (when favorited? + {:style {:color (-> stream + :service-id + utils/get-service-color)}})] + :on-click #(rf/dispatch [(if favorited? :likes/remove :likes/add) + stream + true])} + {:label "Start radio" + :icon [:i.fa-solid.fa-tower-cell] + :on-click #(rf/dispatch [:bg-player/start-radio + stream])} + {:label "Add current to playlist" + :icon [:i.fa-solid.fa-plus] + :on-click #(bookmark stream)} + {:label "Add queue to playlist" + :icon [:i.fa-solid.fa-list] + :on-click #(bookmark queue)} + {:label "Remove from queue" + :icon [:i.fa-solid.fa-trash] + :on-click #(rf/dispatch [:queue/remove + queue-pos])} + {:label "Switch to main" + :icon [:i.fa-solid.fa-display] + :on-click #(rf/dispatch + [:bg-player/switch-to-main])} + {:label "Show channel details" + :icon [:i.fa-solid.fa-user] + :on-click #(rf/dispatch [:navigation/navigate + {:name :channel-page + :params {} + :query {:url + uploader-url}}])} + {:label "Close player" + :icon [:i.fa-solid.fa-close] + :on-click #(rf/dispatch [:bg-player/dispose])}] + :tooltip-classes ["right-5" "bottom-5"] + :extra-classes [:!pl-4 :px-3]])) + (defn extra-controls - [_ _ _] - (let [!menu-active? (r/atom nil)] - (fn [!player {:keys [url uploader-url] :as stream} color] - (let [muted? @(rf/subscribe [:player/muted]) - volume @(rf/subscribe [:player/volume]) - queue @(rf/subscribe [:queue]) - queue-pos @(rf/subscribe [:queue/position]) - bookmarks @(rf/subscribe [:bookmarks]) - liked? (some #(= (:url %) url) - (-> bookmarks - first - :items)) - bookmark #(rf/dispatch [:modals/open [modals/add-to-bookmark %]])] - [:div.flex.lg:justify-end.lg:flex-1.gap-x-2 - [volume-slider !player volume muted? color] - [button - :icon [:i.fa-solid.fa-list] - :on-click #(rf/dispatch [:queue/show true]) - :show-on-mobile? true - :extra-classes [:!pl-4 :!pr-3]] - [layout/popover-menu !menu-active? - [{:label (if liked? "Remove favorite" "Favorite") - :icon [:i.fa-solid.fa-heart - (when liked? {:style {:color color}})] - :on-click #(rf/dispatch [(if liked? :likes/remove :likes/add) - stream true])} - {:label "Start radio" - :icon [:i.fa-solid.fa-tower-cell] - :on-click #(rf/dispatch [:bg-player/start-radio stream])} - {:label "Add current to playlist" - :icon [:i.fa-solid.fa-plus] - :on-click #(bookmark stream)} - {:label "Add queue to playlist" - :icon [:i.fa-solid.fa-list] - :on-click #(bookmark queue)} - {:label "Remove from queue" - :icon [:i.fa-solid.fa-trash] - :on-click #(rf/dispatch [:queue/remove queue-pos])} - {:label "Switch to main" - :icon [:i.fa-solid.fa-display] - :on-click #(rf/dispatch [:bg-player/switch-to-main])} - {:label "Show channel details" - :icon [:i.fa-solid.fa-user] - :on-click #(rf/dispatch [:navigation/navigate - {:name :channel-page - :params {} - :query {:url uploader-url}}])} - {:label "Close player" - :icon [:i.fa-solid.fa-close] - :on-click #(rf/dispatch [:bg-player/dispose])}] - :menu-classes - ["xs:right-5" "xs:top-auto" "xs:left-auto" "xs:bottom-5"] - :extra-classes [:!pl-4 :px-3]]])))) + [!player stream color] + (let [muted? @(rf/subscribe [:player/muted]) + volume @(rf/subscribe [:player/volume])] + [:div.flex.lg:justify-end.lg:flex-1.gap-x-2 + [volume-slider !player volume muted? color] + [button + :icon [:i.fa-solid.fa-list] + :on-click #(rf/dispatch [:queue/show true]) + :show-on-mobile? true + :extra-classes [:!pl-4 :!pr-3]] + [popover stream]])) (defn audio-player [_] diff --git a/src/frontend/tubo/bookmarks/subs.cljs b/src/frontend/tubo/bookmarks/subs.cljs index 1091cb1..be40e5b 100644 --- a/src/frontend/tubo/bookmarks/subs.cljs +++ b/src/frontend/tubo/bookmarks/subs.cljs @@ -6,3 +6,31 @@ :bookmarks (fn [db _] (:bookmarks db))) + +(rf/reg-sub + :bookmarks/bookmarked + (fn [] + (rf/subscribe [:bookmarks])) + (fn [bookmarks [_ id]] + (some #(= (:id %) id) (rest bookmarks)))) + +(rf/reg-sub + :bookmarks/favorited + (fn [] + (rf/subscribe [:bookmarks])) + (fn [bookmarks [_ url]] + (some #(= (:url %) url) + (-> bookmarks + first + :items)))) + +(rf/reg-sub + :bookmarks/playlisted + (fn [] + (rf/subscribe [:bookmarks])) + (fn [bookmarks [_ url playlist-id]] + (some #(= (:url %) url) + (->> bookmarks + (filter #(= (:id %) playlist-id)) + first + :items)))) diff --git a/src/frontend/tubo/bookmarks/views.cljs b/src/frontend/tubo/bookmarks/views.cljs index e92de3a..1c63c96 100644 --- a/src/frontend/tubo/bookmarks/views.cljs +++ b/src/frontend/tubo/bookmarks/views.cljs @@ -9,8 +9,7 @@ (defn bookmarks [] - (let [!menu-active? (r/atom nil) - !layout (r/atom (:items-layout @(rf/subscribe [:settings])))] + (let [!layout (r/atom (:items-layout @(rf/subscribe [:settings])))] (fn [] (let [bookmarks @(rf/subscribe [:bookmarks]) items (map @@ -28,7 +27,7 @@ [layout/content-container [layout/content-header "Bookmarks" [:div.flex.flex-auto - [layout/popover-menu !menu-active? + [layout/popover [{:label "Add New" :icon [:i.fa-solid.fa-plus] :on-click #(rf/dispatch [:modals/open [modals/add-bookmark]])} @@ -37,7 +36,6 @@ {:id "file-selector" :type "file" :multiple "multiple" - :on-click #(reset! !menu-active? true) :on-change #(rf/dispatch [:bookmarks/import (.. % -target -files)])}] [:label.whitespace-nowrap.cursor-pointer.w-full.h-full.absolute.right-0.top-0 @@ -56,8 +54,7 @@ (defn bookmark [] - (let [!menu-active? (r/atom nil) - !layout (r/atom (:items-layout @(rf/subscribe [:settings])))] + (let [!layout (r/atom (:items-layout @(rf/subscribe [:settings])))] (fn [] (let [bookmarks @(rf/subscribe [:bookmarks]) {{:keys [id]} :query-params} @(rf/subscribe @@ -68,7 +65,7 @@ [layout/content-header name (when-not (empty? items) [:div.flex.flex-auto - [layout/popover-menu !menu-active? + [layout/popover [{:label "Add to queue" :icon [:i.fa-solid.fa-headphones] :on-click #(rf/dispatch [:queue/add-n items true])} diff --git a/src/frontend/tubo/channel/views.cljs b/src/frontend/tubo/channel/views.cljs index 102308f..58d5f50 100644 --- a/src/frontend/tubo/channel/views.cljs +++ b/src/frontend/tubo/channel/views.cljs @@ -8,21 +8,18 @@ [tubo.utils :as utils])) (defn metadata-popover - [_] - (let [!menu-active? (r/atom nil)] - (fn [{:keys [related-streams]}] - (when related-streams - [layout/popover-menu !menu-active? - [{:label "Add streams to queue" - :icon [:i.fa-solid.fa-headphones] - :on-click #(rf/dispatch [:queue/add-n related-streams true])} - {:label "Add streams to playlist" - :icon [:i.fa-solid.fa-plus] - :on-click #(rf/dispatch [:modals/open - [modals/add-to-bookmark - related-streams]])}] - :menu-classes - ["xs:right-7" "xs:top-0" "xs:left-auto" "xs:bottom-auto"]])))) + [{:keys [related-streams]}] + (when related-streams + [layout/popover + [{:label "Add streams to queue" + :icon [:i.fa-solid.fa-headphones] + :on-click #(rf/dispatch [:queue/add-n related-streams true])} + {:label "Add streams to playlist" + :icon [:i.fa-solid.fa-plus] + :on-click #(rf/dispatch [:modals/open + [modals/add-to-bookmark + related-streams]])}] + :tooltip-classes ["right-7" "top-0"]])) (defn metadata [{:keys [avatars name subscriber-count] :as channel}] diff --git a/src/frontend/tubo/items/views.cljs b/src/frontend/tubo/items/views.cljs index 3e578f9..78d6776 100644 --- a/src/frontend/tubo/items/views.cljs +++ b/src/frontend/tubo/items/views.cljs @@ -1,68 +1,59 @@ (ns tubo.items.views (:require [re-frame.core :as rf] - [reagent.core :as r] [reitit.frontend.easy :as rfe] [tubo.bookmarks.modals :as bookmarks] [tubo.layout.views :as layout] [tubo.utils :as utils])) (defn item-popover - [_ _] - (let [!menu-active? (r/atom nil)] - (fn [{:keys [service-id audio-streams video-streams type url bookmark-id - uploader-url] - :as item} bookmarks] - (let [liked? (some #(= (:url %) url) - (-> bookmarks - first - :items)) - items - (if (or (= type "stream") audio-streams video-streams) - [{:label "Add to queue" - :icon [:i.fa-solid.fa-headphones] - :on-click #(rf/dispatch [:bg-player/show item true])} - {:label "Start radio" - :icon [:i.fa-solid.fa-tower-cell] - :on-click #(rf/dispatch [:bg-player/start-radio item])} - {:label (if liked? "Remove favorite" "Favorite") - :icon [:i.fa-solid.fa-heart - (when (and liked? service-id) - {:style {:color (utils/get-service-color - service-id)}})] - :on-click #(rf/dispatch [(if liked? :likes/remove :likes/add) - item true])} - {:label "Add to playlist" - :icon [:i.fa-solid.fa-plus] - :on-click #(rf/dispatch [:modals/open - [bookmarks/add-to-bookmark item]])} - (when (some #(= (:url %) url) - (:items (first (filter #(= (:id %) bookmark-id) - bookmarks)))) - {:label "Remove from playlist" - :icon [:i.fa-solid.fa-trash] - :on-click #(rf/dispatch [:bookmark/remove item])}) - {:label "Show channel details" - :icon [:i.fa-solid.fa-user] - :on-click #(rf/dispatch [:navigation/navigate - {:name :channel-page - :params {} - :query {:url uploader-url}}])}] - [(when (and bookmarks - (some #(= (:id %) bookmark-id) (rest bookmarks))) - {:label "Remove playlist" - :icon [:i.fa-solid.fa-trash] - :on-click #(rf/dispatch [:bookmarks/remove bookmark-id - true])})])] - (when (not-empty (remove nil? items)) - [layout/popover-menu !menu-active? items :extra-classes - [:pr-0 :pl-4] :menu-classes - ["xs:right-5" "xs:top-0" "xs:left-auto" "xs:bottom-auto"]]))))) + [{:keys [service-id audio-streams video-streams type url bookmark-id + uploader-url] + :as item}] + (let [favorited? @(rf/subscribe [:bookmarks/favorited url]) + items + (if (or (= type "stream") audio-streams video-streams) + [{:label "Add to queue" + :icon [:i.fa-solid.fa-headphones] + :on-click #(rf/dispatch [:bg-player/show item true])} + {:label "Start radio" + :icon [:i.fa-solid.fa-tower-cell] + :on-click #(rf/dispatch [:bg-player/start-radio item])} + {:label (if favorited? "Remove favorite" "Favorite") + :icon [:i.fa-solid.fa-heart + (when (and favorited? service-id) + {:style {:color (utils/get-service-color + service-id)}})] + :on-click #(rf/dispatch [(if favorited? :likes/remove :likes/add) + item true])} + {:label "Add to playlist" + :icon [:i.fa-solid.fa-plus] + :on-click #(rf/dispatch [:modals/open + [bookmarks/add-to-bookmark item]])} + (when @(rf/subscribe [:bookmarks/playlisted url bookmark-id]) + {:label "Remove from playlist" + :icon [:i.fa-solid.fa-trash] + :on-click #(rf/dispatch [:bookmark/remove item])}) + {:label "Show channel details" + :icon [:i.fa-solid.fa-user] + :on-click #(rf/dispatch [:navigation/navigate + {:name :channel-page + :params {} + :query {:url uploader-url}}])}] + [(when @(rf/subscribe [:bookmarks/bookmarked bookmark-id]) + {:label "Remove playlist" + :icon [:i.fa-solid.fa-trash] + :on-click #(rf/dispatch [:bookmarks/remove bookmark-id + true])})])] + (when (not-empty (remove nil? items)) + [layout/popover items + :extra-classes [:pr-0 :pl-4] + :tooltip-classes ["right-5" "top-0"]]))) (defn grid-item-content [{:keys [url name uploader-url uploader-name subscriber-count view-count stream-count verified? thumbnails duration type] - :as item} route bookmarks] + :as item} route] [:div.flex.flex-col.max-w-full.min-h-full.max-h-full [layout/thumbnail (-> thumbnails @@ -89,7 +80,7 @@ uploader-name]) (when (and uploader-url verified?) [:i.fa-solid.fa-circle-check.text-xs])] - [item-popover item bookmarks]] + [item-popover item]] (when (and (= type "channel") subscriber-count) [:div.flex.items-center [:i.fa-solid.fa-users.text-xs] @@ -108,7 +99,7 @@ (defn list-item-content [{:keys [url name uploader-url uploader-name subscriber-count view-count stream-count verified? thumbnails duration upload-date type] - :as item} route bookmarks] + :as item} route] [:div.flex.gap-x-3.xs:gap-x-5 [layout/thumbnail (-> thumbnails @@ -127,7 +118,7 @@ name (when (and verified? (not uploader-url)) [:i.fa-solid.fa-circle-check.pl-3.text-sm])]] - [item-popover item bookmarks]]) + [item-popover item]]) [:div.flex.items-center.justify-between.gap-y-2 [:div.flex.flex-col.justify-center.gap-y-2.text-neutral-600.dark:text-neutral-400 (when (or uploader-url uploader-name) @@ -173,7 +164,6 @@ (fn [related-streams next-page-url !layout pagination-fn] (let [service-color @(rf/subscribe [:service-color]) pagination-loading? @(rf/subscribe [:show-pagination-loading]) - bookmarks @(rf/subscribe [:bookmarks]) item-url #(case (:type %) "stream" (rfe/href :stream-page nil @@ -210,7 +200,7 @@ {:ref (when (and (seq next-page-url) (= (+ i 1) (count related-streams))) last-item-ref)} - [grid-item-content item (item-url item) bookmarks]])] + [grid-item-content item (item-url item)]])] [:div.flex.flex-wrap.w-full.gap-x-10.gap-y-6 (for [[i item] (map-indexed vector related-streams)] ^{:key i} @@ -218,7 +208,7 @@ {:ref (when (and (seq next-page-url) (= (+ i 1) (count related-streams))) last-item-ref)} - [list-item-content item (item-url item) bookmarks]])])) + [list-item-content item (item-url item)]])])) (when (and pagination-loading? (seq next-page-url)) [layout/loading-icon service-color :text-md])])))) diff --git a/src/frontend/tubo/playlist/views.cljs b/src/frontend/tubo/playlist/views.cljs index 561e1a1..34bbd03 100644 --- a/src/frontend/tubo/playlist/views.cljs +++ b/src/frontend/tubo/playlist/views.cljs @@ -8,21 +8,18 @@ [tubo.layout.views :as layout])) (defn metadata-popover - [_] - (let [!menu-active? (r/atom nil)] - (fn [{:keys [related-streams]}] - (when related-streams - [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]])}] - :menu-classes - ["xs:right-7" "xs:top-0" "xs:left-auto" "xs:bottom-auto"]])))) + [{:keys [related-streams]}] + (when related-streams + [layout/popover + [{: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]])}] + :tooltip-classes ["right-7" "top-0"]])) (defn playlist [_] diff --git a/src/frontend/tubo/queue/views.cljs b/src/frontend/tubo/queue/views.cljs index 474a6c2..3c0c21f 100644 --- a/src/frontend/tubo/queue/views.cljs +++ b/src/frontend/tubo/queue/views.cljs @@ -31,13 +31,13 @@ [:span (utils/get-service-name service-id)]]]]) (defn popover - [{:keys [url service-id uploader-url] :as item} i menu-active? bookmarks] + [{:keys [url service-id uploader-url] :as item} i bookmarks] (let [liked? (some #(= (:url %) url) (-> bookmarks first :items))] [:div.absolute.right-0.top-0.min-h-full.flex.items-center - [layout/popover-menu menu-active? + [layout/popover [{:label (if liked? "Remove favorite" "Favorite") :icon [:i.fa-solid.fa-heart (when liked? @@ -59,20 +59,18 @@ {:name :channel-page :params {} :query {:url uploader-url}}])}] - :menu-classes - ["xs:right-5" "xs:top-0" "xs:left-auto" "xs:bottom-auto"] + :tooltip-classes ["right-5" "top-0" "z-20"] :extra-classes [:px-7 :py-2]]])) (defn queue-item - [_item _queue _queue-pos _i _bookmarks] - (let [!menu-active? (r/atom false) - show-main-player? @(rf/subscribe [:main-player/show])] + [] + (let [show-main-player? @(rf/subscribe [:main-player/show])] (fn [item queue queue-pos i bookmarks] [:div.relative.w-full {:ref #(when (and queue (= queue-pos i) (not show-main-player?)) (rf/dispatch [:scroll-into-view %]))} [item-metadata item queue-pos i] - [popover item i !menu-active? bookmarks]]))) + [popover item i bookmarks]]))) (defn queue-metadata [{:keys [url name uploader-url uploader-name]}] diff --git a/src/frontend/tubo/stream/views.cljs b/src/frontend/tubo/stream/views.cljs index b2cd770..1bbd2df 100644 --- a/src/frontend/tubo/stream/views.cljs +++ b/src/frontend/tubo/stream/views.cljs @@ -11,37 +11,31 @@ [tubo.utils :as utils])) (defn metadata-popover - [_] - (let [!menu-active? (r/atom nil)] - (fn [{:keys [service-id url] :as stream}] - (let [bookmarks @(rf/subscribe [:bookmarks]) - liked? (some #(= (:url %) url) - (-> bookmarks - first - :items))] - [layout/popover-menu !menu-active? - [{:label "Add to queue" - :icon [:i.fa-solid.fa-headphones] - :on-click #(rf/dispatch [:bg-player/show stream true])} - {:label "Start radio" - :icon [:i.fa-solid.fa-tower-cell] - :on-click #(rf/dispatch [:bg-player/start-radio stream])} - {:label (if liked? "Remove favorite" "Favorite") - :icon (if liked? - [:i.fa-solid.fa-heart - {:style {:color (utils/get-service-color service-id)}}] - [:i.fa-solid.fa-heart]) - :on-click #(rf/dispatch [(if liked? :likes/remove :likes/add) stream - true])} - {:label "Original" - :link {:route url :external? true} - :icon [:i.fa-solid.fa-external-link-alt]} - {:label "Add to playlist" - :icon [:i.fa-solid.fa-plus] - :on-click #(rf/dispatch [:modals/open - [modals/add-to-bookmark stream]])}] - :menu-classes ["xs:right-5" "xs:top-5" "xs:left-auto" "xs:bottom-auto"] - :extra-classes ["xs:py-2" "xs:px-4"]])))) + [{:keys [service-id url] :as stream}] + (let [favorited? @(rf/subscribe [:bookmarks/favorited url])] + [layout/popover + [{:label "Add to queue" + :icon [:i.fa-solid.fa-headphones] + :on-click #(rf/dispatch [:bg-player/show stream true])} + {:label "Start radio" + :icon [:i.fa-solid.fa-tower-cell] + :on-click #(rf/dispatch [:bg-player/start-radio stream])} + {:label (if favorited? "Remove favorite" "Favorite") + :icon (if favorited? + [:i.fa-solid.fa-heart + {:style {:color (utils/get-service-color service-id)}}] + [:i.fa-solid.fa-heart]) + :on-click #(rf/dispatch [(if favorited? :likes/remove :likes/add) stream + true])} + {:label "Original" + :link {:route url :external? true} + :icon [:i.fa-solid.fa-external-link-alt]} + {:label "Add to playlist" + :icon [:i.fa-solid.fa-plus] + :on-click #(rf/dispatch [:modals/open + [modals/add-to-bookmark stream]])}] + :tooltip-classes ["right-5" "top-5"] + :extra-classes ["p-3" "xs:py-2" "xs:px-4"]])) (defn metadata-uploader [{:keys [uploader-url uploader-name subscriber-count] :as stream}] @@ -114,9 +108,8 @@ [comments/comments comments-page stream]))))) (defn related-items - [_] - (let [!menu-active? (r/atom nil) - !layout (r/atom (:items-layout @(rf/subscribe [:settings])))] + [] + (let [!layout (r/atom (:items-layout @(rf/subscribe [:settings])))] (fn [{:keys [related-streams]}] (let [show? (:show-related @(rf/subscribe [:settings]))] (when (and show? (seq related-streams)) @@ -124,7 +117,7 @@ [:div.flex.flex-wrap.items-center.justify-between.mt-8.min-w-full [:div.flex.gap-x-4.items-center [:span.font-semibold.text-xl "Next Up"] - [layout/popover-menu !menu-active? + [layout/popover [{:label "Add to queue" :icon [:i.fa-solid.fa-headphones] :on-click #(rf/dispatch [:queue/add-n -- cgit v1.2.3