Compare commits
No commits in common. "de2cf7f9c2f0033e79790bbbdc9eb974e7e4815f" and "7d359c2ed79132d4b76aa999bb9bcdecedb8cc1f" have entirely different histories.
de2cf7f9c2
...
7d359c2ed7
3 changed files with 41 additions and 60 deletions
|
|
@ -18,12 +18,6 @@ After that
|
|||
npm run build
|
||||
```
|
||||
|
||||
You can upload these files to any static file server, for example using `rsync`:
|
||||
|
||||
``` bash
|
||||
rsync -rsvP --delete-after --exclude js/cljs-runtime/ public/ user@server:some/directory
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Just as when building a release, you need to ensure that JS dependencies are installed:
|
||||
|
|
|
|||
|
|
@ -163,12 +163,6 @@
|
|||
}
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
section.posts .controls {
|
||||
grid-template:
|
||||
"a a"
|
||||
"b c";
|
||||
}
|
||||
|
||||
section.posts .controls .post-info {
|
||||
grid-area: a;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
(def posts-init-state
|
||||
{:query nil
|
||||
:last-update -1
|
||||
; TODO: pagination
|
||||
; :page 0
|
||||
; :max-displayed-id nil
|
||||
|
|
@ -43,9 +42,6 @@
|
|||
(defn- promise-reject [val]
|
||||
(js/Promise.reject val))
|
||||
|
||||
(defn- now []
|
||||
(js/Date.now))
|
||||
|
||||
(defn- link-header
|
||||
"Given a JS `Response` object, will parse the `link` header and find a link of
|
||||
a given `link-type` if present. Useful for paginating API requests."
|
||||
|
|
@ -156,6 +152,7 @@
|
|||
(obtain-oauth-authorization-code! application))))))
|
||||
|
||||
(declare fetch-posts!)
|
||||
(declare debounced-refresh!)
|
||||
|
||||
(defn- fetch-application-settings []
|
||||
(->> (db/open-cursor! ::db/application ::db/all)
|
||||
|
|
@ -202,7 +199,7 @@
|
|||
(if (zero? post-count)
|
||||
(fetch-posts! {:instance-url (:instance_url application)
|
||||
:bearer-token (:bearer_token application)})
|
||||
(swap! state assoc-in [:section/posts :last-update] (now))))))))
|
||||
(debounced-refresh! (:section/posts @state))))))))
|
||||
|
||||
;;; views
|
||||
|
||||
|
|
@ -250,7 +247,7 @@
|
|||
on-response on-response
|
||||
on-error on-error}}]
|
||||
((fn paginate! [url]
|
||||
(let [req-id (now)]
|
||||
(let [req-id (js/Date.now)]
|
||||
(js/console.log :paginate! url :max-id max-id :min-id min-id)
|
||||
(swap! state update-in [:section/posts :loading] conj req-id)
|
||||
(-> (mastodon-request! {:url url :bearer-token bearer-token})
|
||||
|
|
@ -274,50 +271,23 @@
|
|||
always prefer to call the most recent call to `f` as close to the delay
|
||||
as possible."
|
||||
[ms f]
|
||||
(let [prev (volatile! (now))]
|
||||
(let [prev (volatile! (js/Date.now))
|
||||
scheduled (volatile! (js/setTimeout (fn dummy []) ms))]
|
||||
(fn debounced-fn [& args]
|
||||
(when (< ms (- (now) @prev))
|
||||
(js/requestAnimationFrame #(apply f args)))
|
||||
(vreset! prev (now)))))
|
||||
(let [now (js/Date.now)]
|
||||
(js/clearTimeout @scheduled)
|
||||
(vreset! scheduled (js/setTimeout (fn []
|
||||
(vreset! prev (js/Date.now))
|
||||
(apply f args))
|
||||
(max 0 (- ms (- now @prev)))))))))
|
||||
|
||||
(defn- refresh-displayed-posts!
|
||||
[{:keys [per-page query]}]
|
||||
(let [; this `xform` is responsible for filtering and building the final list
|
||||
; of results by iterating through the posts in the database.
|
||||
xform (comp
|
||||
(filter (query->matching-fn query))
|
||||
(take per-page)
|
||||
(map #(js->clj % :keywordize-keys true)))
|
||||
refresh-id (now)]
|
||||
(swap! state update-in [:section/posts :loading] conj refresh-id)
|
||||
(. (promise-all [(db/count! ::db/posts)
|
||||
(->> (db/open-cursor! ::db/posts ::db/all
|
||||
{:index ::db/post-created-at
|
||||
:direction :desc})
|
||||
(db/transduce-cursor xform))])
|
||||
(then (fn [[total displayed-posts]]
|
||||
(swap! state update :section/posts #(-> (assoc % :total total)
|
||||
(assoc :displayed-posts displayed-posts)
|
||||
(update :loading disj refresh-id))))))))
|
||||
|
||||
; we use reagent's machinery below to define a callback that runs whenever the
|
||||
; values change that serve as input to the current search reults.
|
||||
|
||||
(def debounced-refresh! (debounce 48 refresh-displayed-posts!))
|
||||
|
||||
(def search-result-inputs (r/reaction (select-keys (:section/posts @state) [:query :per-page :last-update])))
|
||||
|
||||
(defonce update-search-results (r/track! (fn []
|
||||
(let [inputs @search-result-inputs]
|
||||
(debounced-refresh! inputs)))))
|
||||
|
||||
(defn search [{:keys [query]}]
|
||||
(defn search []
|
||||
[:input {:placeholder "Start typing to search…"
|
||||
:type "search"
|
||||
:initial-value query
|
||||
:on-change (fn [e]
|
||||
(let [query (.. e -target -value)]
|
||||
(swap! state assoc-in [:section/posts :query] (if (str/blank? query) nil query))))}])
|
||||
(swap! state assoc-in [:section/posts :query] (if (str/blank? query) nil query))
|
||||
(debounced-refresh! (:section/posts @state))))}])
|
||||
|
||||
(defn- debug
|
||||
"Implements a lazy pretty-printer for whatever is passed in as `obj`. The
|
||||
|
|
@ -399,6 +369,29 @@
|
|||
(js/console.log :logging args)
|
||||
(apply f args)))))
|
||||
|
||||
(defn- refresh-displayed-posts!
|
||||
[posts-section]
|
||||
(let [{:keys [per-page query]} posts-section
|
||||
; this `xform` is responsible for filtering and building the final list
|
||||
; of results by iterating through the posts in the database.
|
||||
xform (comp
|
||||
(filter (query->matching-fn query))
|
||||
(take per-page)
|
||||
(map #(js->clj % :keywordize-keys true)))
|
||||
refresh-id (js/Date.now)]
|
||||
(swap! state update-in [:section/posts :loading] conj refresh-id)
|
||||
(. (promise-all [(db/count! ::db/posts)
|
||||
(->> (db/open-cursor! ::db/posts ::db/all
|
||||
{:index ::db/post-created-at
|
||||
:direction :desc})
|
||||
(db/transduce-cursor xform))])
|
||||
(then (fn [[total displayed-posts]]
|
||||
(swap! state update :section/posts #(-> (assoc % :total total)
|
||||
(assoc :displayed-posts displayed-posts)
|
||||
(update :loading disj refresh-id))))))))
|
||||
|
||||
(def debounced-refresh! (debounce 40 refresh-displayed-posts!))
|
||||
|
||||
(defn- fetch-posts! [opts]
|
||||
(let [defaults {:max-id nil
|
||||
:on-response (fn [response]
|
||||
|
|
@ -417,7 +410,7 @@
|
|||
|
||||
(.get url-params "min_id")
|
||||
(assoc :internal_id (parse-long (.get url-params "min_id")))))))
|
||||
(swap! state assoc-in [:section/posts :last-update] (now)))}]
|
||||
(debounced-refresh! (:section/posts @state)))}]
|
||||
(paginate-posts! (merge defaults opts))))
|
||||
|
||||
(defn- internal-post-id
|
||||
|
|
@ -459,7 +452,7 @@
|
|||
[:path.arc {:d "M50,0 A50,50 180 0,1 100,50"}]]))
|
||||
|
||||
(defn posts-section [{:keys [posts]}]
|
||||
(let [{:keys [per-page query total displayed-posts loading query]} posts
|
||||
(let [{:keys [per-page query total displayed-posts loading]} posts
|
||||
n-displayed (count displayed-posts)]
|
||||
[:section.posts
|
||||
[:h2 "Favorites"]
|
||||
|
|
@ -472,7 +465,7 @@
|
|||
" match"
|
||||
" matches")))))]
|
||||
[:section.search-form
|
||||
[search {:query query}]
|
||||
[search]
|
||||
[loading-indicator {:loading loading}]
|
||||
#_(cond (= api-state :loading) " …"
|
||||
(= api-state :error) " API Error!")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue