108 lines
4 KiB
Clojure
108 lines
4 KiB
Clojure
(ns computersandblues.lodestone.app
|
|
(:require [reagent.core :as r]
|
|
[reagent.dom.client :as rd]
|
|
[clojure.string :as str]
|
|
[clojure.pprint :as pprint]))
|
|
|
|
|
|
(defonce state (r/atom {:root nil
|
|
:query nil
|
|
; TODO: Handle other lists
|
|
:favorites []}))
|
|
|
|
; TODO: Login / Landing Page / Store bearer token in localstorage
|
|
|
|
(defn fetch-favs [{:keys [server-url bearer-token]}]
|
|
; TODO: Pagination
|
|
(let [url (str server-url "/api/v1/favourites")
|
|
auth-header (str "Bearer " bearer-token)]
|
|
(.. (js/fetch url
|
|
#js {:method "GET"
|
|
:headers #js {"Authorization" auth-header}})
|
|
(then (fn [res]
|
|
(if (.-ok res)
|
|
(.then (.json res)
|
|
(fn [body]
|
|
{:raw res
|
|
:body (js->clj body {:keywordize-keys true})}))
|
|
(do
|
|
(println res)
|
|
(throw (ex-info "Could not fetch favorites" {:response res})))))))))
|
|
|
|
(defn search []
|
|
[:input {:placeholder "Start typing to search…"
|
|
:on-change (fn [e]
|
|
(let [query (.. e -target -value)]
|
|
(swap! state assoc :query (if (str/blank? query) nil query))))
|
|
:value (:query @state)}])
|
|
|
|
(defn debug [obj]
|
|
(let [pprinted (r/atom nil)]
|
|
(fn []
|
|
[:details.debug {:on-toggle (fn [_]
|
|
(when-not @pprinted
|
|
(reset! pprinted (with-out-str (pprint/pprint obj)))))}
|
|
[:summary "Inspect"]
|
|
[:pre @pprinted]])))
|
|
|
|
(defn user [{:keys [user]}]
|
|
(:username user))
|
|
|
|
(defn attachment [{:keys [attachment]}]
|
|
(prn attachment)
|
|
(case (:type attachment)
|
|
"image" [:img {:src (:preview_url attachment)
|
|
:alt (:description attachment)}]))
|
|
|
|
(defn post [{:keys [post]}]
|
|
; TODO: handle (:sensitive post)
|
|
; TODO: handle attachments
|
|
[:article
|
|
[:div.users
|
|
[user {:user (:account post)}]
|
|
(when (seq (:mentions post))
|
|
[:span.mentions
|
|
{:style #js {:color "#777"}}
|
|
" (mentioining " (->> (map-indexed (fn [idx account]
|
|
^{:key idx} [user {:user account}])
|
|
(:mentions post))
|
|
(interleave (repeat ", "))
|
|
(drop 1)) ")"])]
|
|
[:div.url [:a {:href (:url post)} (:url post)]]
|
|
[:div.content {:dangerouslySetInnerHTML (r/unsafe-html (:content post))}]
|
|
(when (seq (:media_attachments post))
|
|
[:div.attachments (map-indexed (fn [idx item]
|
|
^{:key idx} [attachment {:attachment item}])
|
|
(:media_attachments post))])
|
|
#_[debug post]])
|
|
|
|
(defn app []
|
|
(let [favorites (:favorites @state)
|
|
query (:query @state)
|
|
matches? (if query
|
|
(partial re-find (js/RegExp. query "i"))
|
|
(constantly true))
|
|
matches (filter (fn [post]
|
|
(or (matches? (:content post))
|
|
(matches? (-> post :account :acct)) ; search for url + username of poster
|
|
(some #(matches? (:username %)) (:mentions post)))) ; search only for username of mentions
|
|
favorites)]
|
|
[:div#app
|
|
[:h1 "Lodestone"]
|
|
[:h2 "Favorites"]
|
|
[:span (str "Loaded " (count favorites) " favorites"
|
|
(when query
|
|
(str ", displaying " (count matches) " matches")))]
|
|
[:div [search]]
|
|
[:ul (map-indexed (fn [idx favorite]
|
|
^{:key idx} [:li [post {:post favorite}]]) matches)]]))
|
|
|
|
(defn ^:dev/after-load render []
|
|
(rd/render (:root @state) [app]))
|
|
|
|
(defn init []
|
|
(-> (fetch-favs {:server-url "https://post.lurk.org"
|
|
:bearer-token "CHANGEME"})
|
|
(.then #(swap! state assoc :favorites (:body %))))
|
|
(swap! state assoc :root (rd/create-root (.-body js/document)))
|
|
(render))
|