aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMiguel Ángel Moreno <mail@migalmoreno.com>2024-12-19 02:56:43 +0100
committerMiguel Ángel Moreno <mail@migalmoreno.com>2024-12-19 03:12:53 +0100
commit591b39568db9383fe3b697315ca984c5eed99dd1 (patch)
treef38e2ef1c25c3fa3e3abfa203fd1bc7d4edb4d62 /src
parent87ae04fd02a11db1d394e647c2c868d293d196ea (diff)
feat: add comments pagination based on IntersectionObserver API
Diffstat (limited to 'src')
-rw-r--r--src/frontend/tubo/comments/events.cljs8
-rw-r--r--src/frontend/tubo/comments/views.cljs81
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])])]))))