From cb974cb498b824ec411b5e2027c69851a628fcb3 Mon Sep 17 00:00:00 2001 From: arne Date: Tue, 18 Nov 2025 16:42:36 +0100 Subject: [PATCH] Handle loading state of parallel long-running updates correctly --- src/computersandblues/lodestone/app.cljs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/computersandblues/lodestone/app.cljs b/src/computersandblues/lodestone/app.cljs index 3e81f6e..8823d79 100644 --- a/src/computersandblues/lodestone/app.cljs +++ b/src/computersandblues/lodestone/app.cljs @@ -1,7 +1,6 @@ (ns computersandblues.lodestone.app (:require [reagent.core :as r] [reagent.dom.client :as rd] - [applied-science.js-interop :as j] [clojure.string :as str] [clojure.pprint :as pprint] [computersandblues.lodestone.database :as db] @@ -16,6 +15,7 @@ ; TODO: Handle other lists :section/posts {:query nil :per-page 50 + :loading #{} ; TODO: pagination ; :page 0 ; :max-displayed-id nil @@ -23,9 +23,7 @@ :total 0 :displayed-posts []}})) - - -; TODO Ensure that user's handles are up to date +; TODO Ensure that cached data is up to date ; TODO Manually fetch older / newer favorites ; TODO Handle 429 ; TODO Search for tags (`#foo`) and handles (`@bar`) @@ -239,17 +237,15 @@ ((fn fetch-favorites' [url] (let [req-id (js/Date.now)] (println :calling url) - (swap! state assoc-in [:section/posts :loading] req-id) + (swap! state update-in [:section/posts :loading] conj req-id) (-> (mastodon-request! {:url url :bearer-token bearer-token}) (.then (fn [response] (on-response response) (if (continue? response) (js/setTimeout #(fetch-favorites' (link-header "next" (:raw response))) 500) - (when (= req-id (-> @state :section/posts :loading)) - (swap! state update :section/posts dissoc :loading))))) + (swap! state update-in [:section/posts :loading] disj req-id)))) (.catch (fn [response] - (when (= req-id (-> @state :section/posts :loading)) - (swap! state update :section/posts dissoc :loading)) + (swap! state update-in [:section/posts :loading] disj req-id) (on-error response)))))) (favorites-url {:instance-url instance-url :max-id max-id}))) @@ -347,14 +343,14 @@ (take per-page) (map #(js->clj % :keywordize-keys true))) refresh-id (js/Date.now)] - (swap! state assoc-in [:section/posts :loading] refresh-id) + (swap! state update-in [:section/posts :loading] conj refresh-id) (-> (js/Promise.all #js [(db/count! ::db/posts) (-> (db/open-cursor! ::db/posts db/all "prev") (db/transduce-cursor xform))]) (.then (fn [[total displayed-posts]] (swap! state update :section/posts #(-> (assoc % :total total) (assoc :displayed-posts displayed-posts) - (cond-> (= refresh-id (:loading %)) (dissoc :loading))))))))) + (update :loading disj refresh-id)))))))) (def debounced-refresh! (debounce 20 (partial refresh-displayed-posts!))) @@ -377,11 +373,11 @@ (str ", displaying " (count displayed-posts) (when query " matches"))))] [:div.search-form [search] - (when loading " …") + (when (seq loading) " …") #_(cond (= api-state :loading) " …" (= api-state :error) " API Error!")]] [:ul.results (map-indexed (fn [idx p] - ^{:key idx} [:li [post {:post p}]]) displayed-posts)] + ^{:key idx} [:li.result [post {:post p}]]) displayed-posts)] #_[:div.load-buttons [:button {:on-click (fn [_]