From 591b39568db9383fe3b697315ca984c5eed99dd1 Mon Sep 17 00:00:00 2001 From: Miguel Ángel Moreno Date: Thu, 19 Dec 2024 02:56:43 +0100 Subject: feat: add comments pagination based on IntersectionObserver API --- src/frontend/tubo/comments/events.cljs | 8 +++- src/frontend/tubo/comments/views.cljs | 81 ++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/frontend/tubo/comments/events.cljs b/src/frontend/tubo/comments/events.cljs index f8122cd..d391edd 100644 --- a/src/frontend/tubo/comments/events.cljs +++ b/src/frontend/tubo/comments/events.cljs @@ -51,6 +51,12 @@ (:next-page (js->clj res :keywordize-keys true))) (assoc :show-pagination-loading false)))) +(rf/reg-event-fx + :comments/bad-paginated-response + (fn [{:keys [db]} [_ res]] + {:fx [[:dispatch [:bad-response res]]] + :db (assoc db :show-pagination-loading false)})) + (rf/reg-event-fx :comments/fetch-paginated (fn [{:keys [db]} [_ url next-page-url]] @@ -59,5 +65,5 @@ {:db (assoc db :show-pagination-loading true) :fx [[:dispatch [:comments/fetch url - [:comments/load-paginated] [:bad-response] + [:comments/load-paginated] [:comments/bad-paginated-response] {:nextPage (js/encodeURIComponent next-page-url)}]]]}))) diff --git a/src/frontend/tubo/comments/views.cljs b/src/frontend/tubo/comments/views.cljs index 524b837..16fdab5 100644 --- a/src/frontend/tubo/comments/views.cljs +++ b/src/frontend/tubo/comments/views.cljs @@ -66,41 +66,54 @@ [:i.fa-solid.fa-turn-down.mx-2.text-xs]]))]]]) (defn comments - [{:keys [comments next-page]} - {:keys [uploader-name uploader-avatars url]}] - (let [pagination-loading? @(rf/subscribe [:show-pagination-loading]) - service-color @(rf/subscribe [:service-color])] - [: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-avatars - last - :url))]] - (when (and replies show-replies) - [:div {:style {:marginLeft "32px"}} - (for [[i reply] (map-indexed vector (:items replies))] - ^{:key i} + [] + (let [!observer (atom nil)] + (fn [{:keys [comments next-page]} + {:keys [uploader-name uploader-avatars url]}] + (let [service-color @(rf/subscribe [:service-color]) + next-page-url (:url next-page) + pagination-loading? @(rf/subscribe [:show-pagination-loading]) + last-item-ref #(when-not pagination-loading? + (when @!observer (.disconnect @!observer)) + (when % + (.observe + (reset! !observer + (js/IntersectionObserver. + (fn [entries] + (when (.-isIntersecting (first + entries)) + (rf/dispatch + [:comments/fetch-paginated url + (:url next-page)]))))) + %)))] + [: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)] + ^{:key i} + [:div.flex.flex-col + {:ref (when (and next-page-url (= (+ i 1) (count comments))) + last-item-ref)} + [:div.flex [comment-item - (assoc reply + (assoc comment :author-name uploader-name :author-avatar (-> uploader-avatars last - :url))])])])]) - (when (:url next-page) - (if pagination-loading? - [layout/loading-icon service-color] - [:div.flex.justify-center - [layout/primary-button - "Show more comments" - #(rf/dispatch [:comments/fetch-paginated url (:url next-page)]) - [:i.fa-solid.fa-plus]]]))])) + :url))]] + (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-avatars + last + :url))])])]) + (when (and pagination-loading? (seq next-page-url)) + [layout/loading-icon service-color :text-md])])])))) -- cgit v1.2.3