Explorar el Código

enhance(capacitor): list graph pages

charlie hace 6 meses
padre
commit
b48c28f75e

+ 1 - 1
shadow-cljs.edn

@@ -104,7 +104,7 @@
                   ;;   For electron devs, assets are located in ./js(via relative path).
                   ;; :dev      {:asset-path "./js"}
                   :devtools {:before-load capacitor.core/stop!          ;; before live-reloading any code call this function
-                             :after-load capacitor.core/start!          ;; after live-reloading finishes call this function
+                             :after-load capacitor.core/render!          ;; after live-reloading finishes call this function
                              :watch-path "/static/capacitor"
                              :preloads [devtools.preload
                                         shadow.remote.runtime.cljs.browser]}}

+ 90 - 75
src/main/capacitor/app.cljs

@@ -1,11 +1,15 @@
 (ns capacitor.app
   (:require ["@capacitor/app" :refer [App]]
             ["@capacitor/status-bar" :refer [StatusBar Style]]
+            [frontend.db.react :as react]
+            [frontend.util :as util]
             [rum.core :as rum]
             [promesa.core :as p]
             [capacitor.ionic :as ionic]
             [capacitor.state :as state]
+            [capacitor.handler :as handler]
             [frontend.state :as fstate]
+            [logseq.db :as ldb]
             [capacitor.pages.settings :as settings]))
 
 (rum/defc app-sidebar []
@@ -18,20 +22,80 @@
       [:div.p-4
        [:strong "hello, logseq?"]])))
 
+(defn- sub-journals
+  []
+  (-> (react/q (fstate/get-current-repo)
+        [:frontend.worker.react/journals]
+        {:async-query-fn (fn []
+                           (p/let [{:keys [data]} (handler/<load-view-data nil {:journals? true})]
+                             (remove nil? data)))}
+        nil)
+    util/react))
+
 (rum/defc home []
-  (let [[open? set-open!] (rum/use-state false)
-        [selected-src set-selected-src] (rum/use-state nil)]
+  (let [[all-pages set-all-pages!] (rum/use-state [])
+        [reload set-reload!] (rum/use-state 0)]
 
     (rum/use-effect!
       (fn []
-        (js/setTimeout
-          (fn []
-            (.setStyle StatusBar #js {:style (.-Light Style)})
-            (.setBackgroundColor StatusBar #js {:color "#ffffff"}))
-          200)
+        (set-all-pages! (handler/get-all-pages))
         #())
-      [])
+      [reload])
+
+    (ionic/ion-content
+      [:div.pt-10.px-6
+       [:h1.text-3xl.font-mono.font-bold.py-2 "Current graph"]
+       [:h2.py-1.text-lg (fstate/get-current-repo)]
+
+       [:div.py-6.flex.justify-center.w-full]
 
+       [:div.flex.justify-between.items-center
+        [:h1.text-3xl.font-mono.font-bold.py-2
+         "All pages"
+         [:small.text-xs.pl-2.opacity-50 (count all-pages)]]
+
+        (ionic/ion-button {:size "small" :fill "clear" :on-click #(set-reload! (inc reload))}
+          [:span {:slot "icon-only"} (ionic/tabler-icon "refresh")])]
+       [:ul.mb-24.pt-2
+        (for [page all-pages]
+          (let [ident (some-> (:block/tags page) first :db/ident)]
+            [:li.font-mono.flex.items-center.py-1.active:opacity-50.active:underline.whitespace-nowrap
+             {:on-click #(js/alert (:block/title page))}
+             (case ident
+               :logseq.class/Property (ionic/tabler-icon "letter-t")
+               :logseq.class/Page (ionic/tabler-icon "file")
+               :logseq.class/Journal (ionic/tabler-icon "calendar")
+               (ionic/tabler-icon "hash"))
+             [:span.pl-1 (:block/title page)]
+             [:code.opacity-30.scale-75 (.toLocaleDateString (js/Date. (:block/created-at page)))]]))]]
+
+      ;; tabbar
+      ;(ionic/ion-tab-bar {:color "light"
+      ;                    :class "w-full fixed bottom-4"}
+      ;  (ionic/ion-tab-button {:tab "tab1"
+      ;                         :selected true
+      ;                         :on-click #(js/alert "home")}
+      ;    (ionic/tabler-icon "home" {:size 22}) "Home")
+      ;  (ionic/ion-tab-button {:tab "tab0"
+      ;                         :selected false}
+      ;    (ionic/tabler-icon "circle-plus" {:size 24}) "Capture New")
+      ;  (ionic/ion-tab-button {:tab "tab2"}
+      ;    (ionic/tabler-icon "settings" {:size 22}) "Settings"))
+      )
+    ))
+
+(rum/defc root <
+  rum/reactive
+  {:did-mount
+   (fn [s]
+     (js/setTimeout
+       (fn []
+         (.setStyle StatusBar #js {:style (.-Light Style)})
+         (.setBackgroundColor StatusBar #js {:color "#ffffff"}))
+       300)
+     s)}
+  []
+  (let [db-restoring? (fstate/sub :db/restoring?)]
     [:<>
      (app-sidebar)
 
@@ -41,72 +105,22 @@
          (ionic/ion-toolbar
            (ionic/ion-buttons {:slot "start"}
              (ionic/ion-menu-button)
-             (ionic/ion-button {:class "opacity-90"} (ionic/tabler-icon "search" {:size 22 :stroke 2}))
-             )
-           [:a.px-2 {:slot "end"}
-            (ionic/tabler-icon "help" {:size 24 :class "opacity-70"})]))
-       (ionic/ion-content
-         [:div.pt-10.px-8
-          [:h1.text-3xl.font-mono.font-bold.py-2 "Suggested"]
-          [:h2 (fstate/get-current-repo)]
-          [:p.flex.py-4.justify-center.bg-gray-03.flex-col.gap-6
-           (ionic/ion-button {:on-click #(js/alert "hello click me!")
-                              :size "large"}
-             "Default primary")
-           (ionic/ion-button {:color "warning"
-                              :size "large"
-                              :fill "outline"
-                              :on-click #(set-open! true)} "Primary Button")
-           (ionic/ion-button {:color "success"
-                              :size "large"
-                              :on-click
-                              (fn []
-                                (-> ionic/ionic-camera
-                                  (.getPhoto
-                                    #js {:source "PHOTOS"
-                                         :resultType (.-DataUrl ionic/ionic-camera-result-type)})
-                                  (p/then #(set-selected-src (.-dataUrl %)))))}
-             [:span.pl-2 {:slot "end"} (ionic/tabler-icon "cloud-upload" {:size 22})]
-             [:strong "获取图片"]
-             (ionic/ion-badge {:color "danger"} "99+"))
-
-           [:<>
-            (ionic/ion-datetime-button {:datetime "datetime"})
-            (ionic/ion-modal
-              {:keepContentsMounted true}
-              (ionic/ion-datetime {:id "datetime"}))]]
-
-          [:div.p-4.flex.justify-center
-           (ionic/ion-nav-link
-             {:routerDirection "forward"
-              :component settings/page}
-             (ionic/ion-button {:size "large"} "Go to settings page")
-             )]
-
-          ;; selected image
-          (when selected-src
-            [:p.p-3.flex.items-center.justify-center
-             [:img {:src selected-src :width "70%"}]])
-
-          ;; alert
-          (ionic/ion-alert {:is-open open?
-                            :onDidDismiss #(set-open! false)
-                            :buttons ["Action"]
-                            :message "hello alert?"})]
-
-         ;; tabbar
-         ;(ionic/ion-tab-bar {:color "light"
-         ;                    :class "w-full fixed bottom-4"}
-         ;  (ionic/ion-tab-button {:tab "tab1"
-         ;                         :selected true
-         ;                         :on-click #(js/alert "home")}
-         ;    (ionic/tabler-icon "home" {:size 22}) "Home")
-         ;  (ionic/ion-tab-button {:tab "tab0"
-         ;                         :selected false}
-         ;    (ionic/tabler-icon "circle-plus" {:size 24}) "Capture New")
-         ;  (ionic/ion-tab-button {:tab "tab2"}
-         ;    (ionic/tabler-icon "settings" {:size 22}) "Settings"))
-         ))]))
+             (ionic/ion-button {:class "opacity-90"} (ionic/tabler-icon "search" {:size 22 :stroke 2})))
+
+           (ionic/ion-button
+             {:slot "end"
+              :fill "clear"}
+             (ionic/ion-nav-link
+               {:routerDirection "forward"
+                :class "w-full"
+                :component settings/page}
+               (ionic/tabler-icon "help" {:size 24 :class "opacity-70"})))))
+       ;; main content
+       (if db-restoring?
+         (ionic/ion-content
+           [:strong.flex.justify-center.items-center.py-24
+            (ionic/tabler-icon "loader" {:class "animate animate-spin opacity-50" :size 30})])
+         (home)))]))
 
 (rum/defc main []
   (let [nav-ref (rum/use-ref nil)
@@ -126,6 +140,7 @@
         (set-nav-root! (rum/deref nav-ref))
         #())
       [(rum/deref nav-ref)])
+
     [:> (.-IonApp ionic/ionic-react)
-     (ionic/ion-nav {:ref nav-ref :root home
+     (ionic/ion-nav {:ref nav-ref :root root
                      :animated true :swipeGesture false})]))

+ 110 - 0
src/main/capacitor/bootstrap.cljs

@@ -0,0 +1,110 @@
+(ns capacitor.bootstrap
+  (:require [cljs-bean.core :as bean]
+            [electron.listener :as el]
+            [frontend.config :as config]
+            [frontend.context.i18n :as i18n]
+            [frontend.db.react :as react]
+            [frontend.db.restore :as db-restore]
+            [frontend.error :as error]
+            [capacitor.events :as events]
+            [frontend.handler.global-config :as global-config-handler]
+            [frontend.handler.notification :as notification]
+            [frontend.handler.page :as page-handler]
+            [frontend.handler.plugin-config :as plugin-config-handler]
+            [frontend.handler.repo :as repo-handler]
+            [frontend.handler.repo-config :as repo-config-handler]
+            [frontend.handler.test :as test]
+            [frontend.idb :as idb]
+            [frontend.persist-db :as persist-db]
+            [frontend.persist-db.browser :as db-browser]
+            [frontend.state :as state]
+            [frontend.util :as util]
+            [frontend.util.persist-var :as persist-var]
+            [goog.object :as gobj]
+            [lambdaisland.glogi :as log]
+            [promesa.core :as p]))
+
+(defn restore-and-setup!
+  [repo]
+  (when repo
+    (-> (p/let [_ (db-restore/restore-graph! repo)]
+          (repo-config-handler/start {:repo repo}))
+      (p/then
+        (fn []
+          (js/console.log "db restored, setting up repo hooks")
+
+          ; skip initialize ui commands
+          ;(page-handler/init-commands!)
+          ))
+      (p/catch (fn [error]
+                 (log/error :exception error))))))
+
+(defn- handle-connection-change
+  [e]
+  (let [online? (= (gobj/get e "type") "online")]
+    (state/set-online! online?)))
+
+(defn set-network-watcher!
+  []
+  (js/window.addEventListener "online" handle-connection-change)
+  (js/window.addEventListener "offline" handle-connection-change))
+
+;(defn- get-system-info
+;  []
+;  (when (util/electron?)
+;    (p/let [info (ipc/ipc :system/info)]
+;      (state/set-state! :system/info (bean/->clj info)))))
+
+(defn start!
+  [render]
+
+  (idb/start)
+  ;(get-system-info)
+  ;(set-global-error-notification!)
+
+  ;(user-handler/restore-tokens-from-localstorage)
+  (state/set-db-restoring! true)
+
+  (render)
+
+  (i18n/start)
+
+  (state/set-online! js/navigator.onLine)
+  (set-network-watcher!)
+
+  (-> (util/indexeddb-check?)
+    (p/catch (fn [_e]
+               (notification/show! "Sorry, it seems that your browser doesn't support IndexedDB, we recommend to use latest Chrome(Chromium) or Firefox(Non-private mode)." :error false)
+               (state/set-indexedb-support! false))))
+
+  (react/run-custom-queries-when-idle!)
+
+  (events/run!)
+
+  (p/do!
+    (-> (p/let [_ (db-browser/start-db-worker!)
+                repos (repo-handler/get-repos)
+                _ (state/set-repos! repos)
+                ;_ (mobile-util/hide-splash) ;; hide splash as early as ui is stable
+                repo (or (state/get-current-repo) (:url (first repos)))
+                _ (if (empty? repos)
+                    (repo-handler/new-db! config/demo-repo)
+                    (restore-and-setup! repo))]
+
+          (prn :debug-start-repos repos)
+          ;(when (util/electron?)
+          ;  (persist-db/run-export-periodically!))
+          ;(when (mobile-util/native-platform?)
+          ;  (state/restore-mobile-theme!))
+          )
+      (p/catch (fn [e]
+                 (js/console.error "Error while restoring repos: " e)))
+      (p/finally (fn []
+                   (state/set-db-restoring! false))))
+
+    (util/<app-wake-up-from-sleep-loop (atom false))
+
+    (persist-var/load-vars)))
+
+(defn stop! []
+  (prn "stop!"))

+ 3 - 3
src/main/capacitor/core.cljs

@@ -1,11 +1,11 @@
 (ns capacitor.core
   (:require ["react-dom/client" :as rdc]
             [capacitor.app :as app]
-            [capacitor.handler :as handler]))
+            [capacitor.bootstrap :as bootstrap]))
 
 (defonce ^js root (rdc/createRoot (.getElementById js/document "root")))
 
-(defn ^:export start!
+(defn ^:export render!
   []
   (.render root (app/main)))
 
@@ -14,7 +14,7 @@
   ;; this is called in the index.html and must be exported
   ;; so it is available even in :advanced release builds
   (prn "[capacitor-new] init!")
-  (handler/start! start!))
+  (bootstrap/start! render!))
 
 (defn ^:export stop! []
   ;; stop is called before any code is reloaded

+ 12 - 157
src/main/capacitor/handler.cljs

@@ -1,164 +1,19 @@
 (ns capacitor.handler
-  (:require [cljs-bean.core :as bean]
-            ;[electron.ipc :as ipc]
-            [electron.listener :as el]
-            [frontend.config :as config]
-            [frontend.context.i18n :as i18n]
-            [frontend.db.react :as react]
-            [frontend.db.restore :as db-restore]
-            [frontend.error :as error]
-            [capacitor.events :as events]
-            ;[frontend.handler.events :as events]
-            ;[frontend.handler.file-based.events]
-            ;[frontend.handler.file-based.file :as file-handler]
-            [frontend.handler.global-config :as global-config-handler]
-            [frontend.handler.notification :as notification]
-            [frontend.handler.page :as page-handler]
-            [frontend.handler.plugin-config :as plugin-config-handler]
+  (:require [logseq.db :as ldb]
+            [frontend.db.conn :as db-conn]
+            [frontend.state :as fstate]
             [frontend.handler.repo :as repo-handler]
-            [frontend.handler.repo-config :as repo-config-handler]
-            [frontend.handler.test :as test]
-            ;[frontend.handler.ui :as ui-handler]
-            ;[frontend.handler.user :as user-handler]
-            [frontend.idb :as idb]
-            ;[frontend.mobile.core :as mobile]
-            ;[frontend.mobile.util :as mobile-util]
-            ;[frontend.modules.shortcut.core :as shortcut]
-            [frontend.persist-db :as persist-db]
-            [frontend.persist-db.browser :as db-browser]
-            [frontend.state :as state]
-            [frontend.util :as util]
-            [frontend.util.persist-var :as persist-var]
-            [goog.object :as gobj]
+            [frontend.handler.page :as page-handler]
             [lambdaisland.glogi :as log]
             [promesa.core :as p]))
 
-(defn- set-global-error-notification!
-  []
-  (when-not config/dev?
-    (set! js/window.onerror
-      (fn [message, _source, _lineno, _colno, error]
-        (when-not (error/ignored? message)
-          (js/console.error message)
-          (log/error :exception error))))))
-
-;(defn- watch-for-date!
-;  []
-;  (let [f (fn []
-;            (let [repo (state/get-current-repo)]
-;              (when (or
-;                      (config/db-based-graph? repo)
-;                      (and (not (state/nfs-refreshing?))
-;                        (not (contains? (:file/unlinked-dirs @state/state)
-;                               (config/get-repo-dir repo)))))
-;                ;; Don't create the journal file until user writes something
-;                (page-handler/create-today-journal!))))]
-;    (f)
-;    (js/setInterval f 5000)))
-
-(defn restore-and-setup!
-  [repo]
-  (when repo
-    (-> (p/let [_ (db-restore/restore-graph! repo)]
-          (repo-config-handler/start {:repo repo}))
-      (p/then
-        (fn []
-          ;; try to load custom css only for current repo
-          ;(ui-handler/add-style-if-exists!)
-
-          (->
-            (p/do!
-              (when (config/global-config-enabled?)
-                (global-config-handler/start {:repo repo}))
-              (when (config/plugin-config-enabled?)
-                (plugin-config-handler/start)))
-            (p/finally
-              (fn []
-                ;; install after config is restored
-                ;(shortcut/refresh!)
-
-                (state/set-db-restoring! false))))))
-      (p/then
-        (fn []
-          (js/console.log "db restored, setting up repo hooks")
-
-          ;(state/pub-event! [:modal/nfs-ask-permission])
-
-          (page-handler/init-commands!)
-
-          ;(watch-for-date!)
-          ;(when (and (not (config/db-based-graph? repo)) (util/electron?))
-          ;  (file-handler/watch-for-current-graph-dir!))
-          ))
-      (p/catch (fn [error]
-                 (log/error :exception error))))))
-
-(defn- handle-connection-change
-  [e]
-  (let [online? (= (gobj/get e "type") "online")]
-    (state/set-online! online?)))
-
-(defn set-network-watcher!
-  []
-  (js/window.addEventListener "online" handle-connection-change)
-  (js/window.addEventListener "offline" handle-connection-change))
-
-;(defn- get-system-info
-;  []
-;  (when (util/electron?)
-;    (p/let [info (ipc/ipc :system/info)]
-;      (state/set-state! :system/info (bean/->clj info)))))
-
-(defn start!
-  [render]
-
-  (idb/start)
-  ;(get-system-info)
-  (set-global-error-notification!)
-
-  ;(user-handler/restore-tokens-from-localstorage)
-  (state/set-db-restoring! true)
-
-  (render)
-
-  (i18n/start)
-
-  (state/set-online! js/navigator.onLine)
-  (set-network-watcher!)
-
-  (-> (util/indexeddb-check?)
-    (p/catch (fn [_e]
-               (notification/show! "Sorry, it seems that your browser doesn't support IndexedDB, we recommend to use latest Chrome(Chromium) or Firefox(Non-private mode)." :error false)
-               (state/set-indexedb-support! false))))
-
-  (react/run-custom-queries-when-idle!)
-
-  (events/run!)
-
-  (p/do!
-    ;(when (mobile-util/native-platform?)
-    ;  (mobile/mobile-preinit))
-    (-> (p/let [_ (db-browser/start-db-worker!)
-                repos (repo-handler/get-repos)
-                _ (state/set-repos! repos)
-                ;_ (mobile-util/hide-splash) ;; hide splash as early as ui is stable
-                repo (or (state/get-current-repo) (:url (first repos)))
-                _ (if (empty? repos)
-                    (repo-handler/new-db! config/demo-repo)
-                    (restore-and-setup! repo))]
-          (when (util/electron?)
-            (persist-db/run-export-periodically!))
-          ;(when (mobile-util/native-platform?)
-          ;  (state/restore-mobile-theme!))
-          )
-      (p/catch (fn [e]
-                 (js/console.error "Error while restoring repos: " e)))
-      (p/finally (fn []
-                   (state/set-db-restoring! false))))
-
-    (util/<app-wake-up-from-sleep-loop (atom false))
+(defn <load-view-data
+  [view opts]
+  (fstate/<invoke-db-worker :thread-api/get-view-data
+    (fstate/get-current-repo) (:db/id view) opts))
 
-    (persist-var/load-vars)))
+(defn ui-db []
+  (db-conn/get-db))
 
-(defn stop! []
-  (prn "stop!"))
+(defn get-all-pages []
+  (some->> (ui-db) (ldb/get-all-pages) (sort-by :block/created-at) (reverse)))

+ 1 - 0
src/main/capacitor/hooks.cljs

@@ -0,0 +1 @@
+(ns capacitor.hooks)

+ 1 - 0
src/main/capacitor/ionic.cljs

@@ -19,6 +19,7 @@
 (defonce ion-back-button (shui-util/react->rum (.-IonBackButton ionic-react) false))
 (defonce ion-buttons (shui-util/react->rum (.-IonButtons ionic-react) true))
 (defonce ion-toolbar (shui-util/react->rum (.-IonToolbar ionic-react) true))
+(defonce ion-loading (shui-util/react->rum (.-IonLoading ionic-react) true))
 (defonce ion-title (shui-util/react->rum (.-IonTitle ionic-react) true))
 (defonce ion-button (shui-util/react->rum (.-IonButton ionic-react) true))
 (defonce ion-alert (shui-util/react->rum (.-IonAlert ionic-react) true))