From 9ef93c8d66b394ecccccfcf9354cd826d3a24099 Mon Sep 17 00:00:00 2001 From: Miguel Ángel Moreno Date: Sun, 28 Jan 2024 02:55:02 +0100 Subject: feat(frontend): add show-more layout component --- src/frontend/tubo/components/layout.cljs | 34 +++++++++++++++++++ src/frontend/tubo/views/channel.cljs | 58 +++++++++++++++++--------------- src/frontend/tubo/views/stream.cljs | 21 +++++------- 3 files changed, 73 insertions(+), 40 deletions(-) (limited to 'src/frontend') diff --git a/src/frontend/tubo/components/layout.cljs b/src/frontend/tubo/components/layout.cljs index 0595ab5..0bcfac0 100644 --- a/src/frontend/tubo/components/layout.cljs +++ b/src/frontend/tubo/components/layout.cljs @@ -1,5 +1,6 @@ (ns tubo.components.layout (:require + [reagent.core :as r] [re-frame.core :as rf])) (defn logo [] @@ -87,3 +88,36 @@ right-button] (when open? (map-indexed #(with-meta %2 {:key %1}) content))]) + +(defn show-more-container + [open? text on-open] + (let [!text-container (atom nil) + !resize-observer (atom nil) + text-clamped? (r/atom nil)] + (r/create-class + {:display-name "ShowMoreContainer" + :component-did-mount + (fn [_] + (when @!text-container + (.observe + (reset! !resize-observer + (js/ResizeObserver. + #(let [target (.-target (first %))] + (reset! text-clamped? + (> (.-scrollHeight target) + (.-clientHeight target)))))) + @!text-container))) + :component-will-unmount + #(when (and @!resize-observer @!text-container) + (.unobserve @!resize-observer @!text-container)) + :reagent-render + (fn [open? text on-open] + [:div.py-3.flex.flex-wrap.min-w-full + [:div {:dangerouslySetInnerHTML {:__html text} + :class (when-not open? "line-clamp-2") + :ref #(reset! !text-container %)}] + (when (or @text-clamped? open?) + [:div.flex.justify-center.min-w-full.py-4 + [secondary-button + (if (not open?) "Show More" "Show Less") + on-open]])])}))) diff --git a/src/frontend/tubo/views/channel.cljs b/src/frontend/tubo/views/channel.cljs index 00dc12f..1278828 100644 --- a/src/frontend/tubo/views/channel.cljs +++ b/src/frontend/tubo/views/channel.cljs @@ -1,35 +1,39 @@ (ns tubo.views.channel (:require + [reagent.core :as r] [re-frame.core :as rf] [tubo.components.items :as items] [tubo.components.layout :as layout] [tubo.events :as events])) (defn channel - [{{:keys [url]} :query-params}] - (let [{:keys [banner avatar name description subscriber-count - related-streams next-page]} @(rf/subscribe [:channel]) - next-page-url (:url next-page) - service-color @(rf/subscribe [:service-color]) - scrolled-to-bottom? @(rf/subscribe [:scrolled-to-bottom])] - (when scrolled-to-bottom? - (rf/dispatch [::events/channel-pagination url next-page-url])) - [layout/content-container - (when banner - [:div.flex.justify-center - [:img.min-w-full {:src banner}]]) - [:div.flex.items-center.justify-between - [:div.flex.items-center.my-4.mx-2 - [layout/uploader-avatar avatar name] - [:div.m-4 - [:h1.text-xl name] - (when subscriber-count - [:div.flex.my-2.items-center - [:i.fa-solid.fa-users.text-xs] - [:span.mx-2 (.toLocaleString subscriber-count)]])]] - [layout/primary-button "Enqueue" - #(rf/dispatch [::events/enqueue-related-streams related-streams service-color]) - "fa-solid fa-headphones"]] - [:div.my-2 - [:p description]] - [items/related-streams related-streams next-page-url]])) + [query-params] + (let [!show-description? (r/atom false)] + (fn [{{:keys [url]} :query-params}] + (let [{:keys [banner avatar name description subscriber-count + related-streams next-page + donation-links] :as channel} @(rf/subscribe [:channel]) + next-page-url (:url next-page) + service-color @(rf/subscribe [:service-color]) + scrolled-to-bottom? @(rf/subscribe [:scrolled-to-bottom])] + (when scrolled-to-bottom? + (rf/dispatch [::events/channel-pagination url next-page-url])) + [layout/content-container + (when banner + [:div.flex.justify-center.h-24 + [:img.min-w-full.min-h-full.object-cover {:src banner}]]) + [:div.flex.items-center.justify-between + [:div.flex.items-center.my-4.mx-2 + [layout/uploader-avatar avatar name] + [:div.m-4 + [:h1.text-xl name] + (when subscriber-count + [:div.flex.my-2.items-center + [:i.fa-solid.fa-users.text-xs] + [:span.mx-2 (.toLocaleString subscriber-count)]])]] + [layout/primary-button "Enqueue" + #(rf/dispatch [::events/enqueue-related-streams related-streams service-color]) + "fa-solid fa-headphones"]] + [layout/show-more-container @!show-description? description + #(reset! !show-description? (not @!show-description?))] + [items/related-streams related-streams next-page-url]])))) diff --git a/src/frontend/tubo/views/stream.cljs b/src/frontend/tubo/views/stream.cljs index 232d134..b609511 100644 --- a/src/frontend/tubo/views/stream.cljs +++ b/src/frontend/tubo/views/stream.cljs @@ -99,22 +99,17 @@ [:i.fa-solid.fa-calendar] [:span.ml-2 (util/format-date-string upload-date)]])]] (when (and show-description? (not (empty? description))) - [:div.py-3.flex.flex-wrap.min-w-full - [:div {:dangerouslySetInnerHTML {:__html description} - :class (when (not show-description) "line-clamp-2")}] - [:div.flex.justify-center.font-bold.min-w-full.py-4.cursor-pointer - [layout/secondary-button - (if (not show-description) "Show More" "Show Less") - #(rf/dispatch [::events/toggle-stream-layout :show-description])]]]) + [layout/show-more-container show-description description + #(rf/dispatch [::events/toggle-stream-layout :show-description])]) (when (and comments-page (not (empty? (:comments comments-page))) show-comments?) [layout/accordeon - {:label "Comments" - :on-open #(if show-comments - (rf/dispatch [::events/toggle-stream-layout :show-comments]) - (if comments-page + {:label "Comments" + :on-open #(if show-comments (rf/dispatch [::events/toggle-stream-layout :show-comments]) - (rf/dispatch [::events/get-comments url]))) - :open? show-comments + (if comments-page + (rf/dispatch [::events/toggle-stream-layout :show-comments]) + (rf/dispatch [::events/get-comments url]))) + :open? show-comments :left-icon "fa-solid fa-comments"} (if show-comments-loading [layout/loading-icon service-color "text-2xl"] -- cgit v1.2.3