diff options
author | Miguel Ángel Moreno <mail@migalmoreno.com> | 2024-12-19 02:56:43 +0100 |
---|---|---|
committer | Miguel Ángel Moreno <mail@migalmoreno.com> | 2024-12-19 03:12:53 +0100 |
commit | 591b39568db9383fe3b697315ca984c5eed99dd1 (patch) | |
tree | f38e2ef1c25c3fa3e3abfa203fd1bc7d4edb4d62 /src | |
parent | 87ae04fd02a11db1d394e647c2c868d293d196ea (diff) |
feat: add comments pagination based on IntersectionObserver API
Diffstat (limited to 'src')
-rw-r--r-- | src/frontend/tubo/comments/events.cljs | 8 | ||||
-rw-r--r-- | 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 @@ -52,6 +52,12 @@ (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]] (if (empty? 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])])])))) |