Sfoglia il codice sorgente

perf: use virtualized list instead of our own ui/infinite-list

The benefits are:
1. less journals to render, so less memory, faster editor experience
2. our old implementation is buggy in some platforms
Tienson Qin 1 anno fa
parent
commit
2ba01c7cef

+ 1 - 0
package.json

@@ -151,6 +151,7 @@
         "react-textarea-autosize": "8.3.3",
         "react-tippy": "1.4.0",
         "react-transition-group": "4.3.0",
+        "react-virtuoso": "^4.7.11",
         "remove-accents": "0.4.2",
         "reveal.js": "^4.5.0",
         "sanitize-filename": "1.6.3",

+ 22 - 16
src/main/frontend/components/journal.cljs

@@ -5,30 +5,36 @@
             [frontend.handler.page :as page-handler]
             [frontend.state :as state]
             [frontend.ui :as ui]
-            [rum.core :as rum]))
+            [rum.core :as rum]
+            [goog.dom :as gdom]
+            [frontend.util :as util]))
 
 (rum/defc journal-cp < rum/reactive
   [page]
-  (let [repo (state/sub :git/current-repo)]
-    (page/page {:repo repo
-                :page-name (str (:block/uuid page))})))
+  [:div.journal-item.content {:key (:db/id page)}
+   (let [repo (state/sub :git/current-repo)]
+     (page/page {:repo repo
+                 :page-name (str (:block/uuid page))}))])
 
 (rum/defc journals < rum/reactive
   {:will-unmount (fn [state]
-                   (state/set-journals-length! 1)
+                   (state/set-journals-length! 3)
                    state)}
   [latest-journals]
-  [:div#journals
-   (ui/infinite-list
-    "main-content-container"
-    (for [{:block/keys [name] :as page} latest-journals]
-      [:div.journal-item.content {:key name}
-       (journal-cp page)])
-    {:has-more (page-handler/has-more-journals?)
-     :more-class "text-4xl"
-     :on-top-reached page-handler/create-today-journal!
-     :on-load (fn []
-                (page-handler/load-more-journals!))})])
+  (when (seq latest-journals)
+    [:div#journals
+     (ui/virtuoso
+      {:use-window-scroll true
+       :custom-scroll-parent (gdom/getElement "main-content-container")
+       :initial-item-count 1
+       :total-count (count latest-journals)
+       :item-content (fn [idx]
+                       (when-let [page (util/nth-safe latest-journals idx)]
+                         (journal-cp page)))
+       :start-reached (fn [_idx]
+                        (page-handler/create-today-journal!))
+       :end-reached (fn [_idx]
+                      (page-handler/load-more-journals!))})]))
 
 (rum/defc all-journals < rum/reactive db-mixins/query
   []

+ 0 - 1
src/main/frontend/fs/node.cljs

@@ -6,7 +6,6 @@
             [frontend.config :as config]
             [frontend.db :as db]
             [frontend.fs.protocol :as protocol]
-            [frontend.state :as state]
             [frontend.util :as util]
             [goog.object :as gobj]
             [lambdaisland.glogi :as log]

+ 1 - 1
src/main/frontend/state.cljs

@@ -55,7 +55,7 @@
       :draw?                   false
       :db/restoring?           nil
 
-      :journals-length                       1
+      :journals-length                       3
 
       :search/q                              ""
       :search/mode                           nil ; nil -> global mode, :graph -> add graph filter, etc.

+ 3 - 50
src/main/frontend/ui.cljs

@@ -6,6 +6,7 @@
             ["react-textarea-autosize" :as TextareaAutosize]
             ["react-tippy" :as react-tippy]
             ["react-transition-group" :refer [CSSTransition TransitionGroup]]
+            ["react-virtuoso" :refer [Virtuoso]]
             ["@emoji-mart/data" :as emoji-data]
             ["emoji-mart" :as emoji-mart]
             [cljs-bean.core :as bean]
@@ -28,7 +29,6 @@
             [frontend.util :as util]
             [frontend.util.cursor :as cursor]
             [goog.dom :as gdom]
-            [goog.functions :refer [debounce]]
             [goog.object :as gobj]
             [lambdaisland.glogi :as log]
             [logseq.shui.icon.v2 :as shui.icon.v2]
@@ -42,6 +42,8 @@
 (defonce transition-group (r/adapt-class TransitionGroup))
 (defonce css-transition (r/adapt-class CSSTransition))
 (defonce textarea (r/adapt-class (gobj/get TextareaAutosize "default")))
+(defonce virtuoso (r/adapt-class Virtuoso))
+
 (def resize-provider (r/adapt-class (gobj/get Resize "ResizeProvider")))
 (def resize-consumer (r/adapt-class (gobj/get Resize "ResizeConsumer")))
 (def Tippy (r/adapt-class (gobj/get react-tippy "Tooltip")))
@@ -389,9 +391,6 @@
   (when-let [element ^js (gdom/getElement element)]
     (.focus element)))
 
-(defn get-scroll-top []
-  (.-scrollTop (main-node)))
-
 (defn get-dynamic-style-node
   []
   (js/document.getElementById "dynamic-style-scope"))
@@ -490,52 +489,6 @@
       (handler)
       #(.removeEventListener js/window.visualViewport "resize" handler))))
 
-(defonce last-scroll-top (atom 0))
-
-(defn scroll-down?
-  []
-  (let [scroll-top (get-scroll-top)
-        down? (> scroll-top @last-scroll-top)]
-    (reset! last-scroll-top scroll-top)
-    down?))
-
-(defn on-scroll
-  [node {:keys [on-load on-top-reached threshold bottom-reached]
-         :or {threshold 500}}]
-  (let [scroll-top (gobj/get node "scrollTop")
-        bottom-reached? (if (fn? bottom-reached)
-                          (bottom-reached)
-                          (util/bottom-reached? node threshold))
-        top-reached? (= scroll-top 0)
-        down? (scroll-down?)]
-    (when (and bottom-reached? down? on-load)
-      (on-load))
-    (when (and (not down?) top-reached? on-top-reached)
-      (on-top-reached))))
-
-(defn attach-listeners
-  "Attach scroll and resize listeners."
-  [state]
-  (let [list-element-id (first (:rum/args state))
-        opts (-> state :rum/args (nth 2))
-        node (js/document.getElementById list-element-id)
-        debounced-on-scroll (debounce #(on-scroll node opts) 100)]
-    (mixins/listen state node :scroll debounced-on-scroll)))
-
-(rum/defcs infinite-list <
-  (mixins/event-mixin attach-listeners)
-  "Render an infinite list."
-  [state _list-element-id body {:keys [on-load has-more more more-class]
-                                :or {more-class "text-sm"}}]
-  [:div
-   body
-   (when has-more
-     [:div.w-full.p-4
-      [:a.fade-link.text-link.font-bold
-       {:on-click on-load
-        :class more-class}
-       (or more (t :page/earlier))]])])
-
 (rum/defcs auto-complete <
   (rum/local 0 ::current-idx)
   (shortcut/mixin* :shortcut.handler/auto-complete)

+ 0 - 8
src/main/frontend/util.cljc

@@ -541,14 +541,6 @@
                            #js {:behavior (if animate? "smooth" "auto")
                                 :block    "center"}))))))
 
-#?(:cljs
-   (defn bottom-reached?
-     [node threshold]
-     (let [full-height (gobj/get node "scrollHeight")
-           scroll-top (gobj/get node "scrollTop")
-           client-height (gobj/get node "clientHeight")]
-       (<= (- full-height scroll-top client-height) threshold))))
-
 #?(:cljs
    (defn link?
      [node]

+ 0 - 1
src/resources/dicts/de.edn

@@ -266,7 +266,6 @@
  :page/created-at "Erstellt am"
  :page/delete "Seite löschen"
  :page/delete-confirmation "Diese Seite und die zugehörige Datei löschen?"
- :page/earlier "Früher"
  :page/illegal-page-name "Seitenname nicht zulässig!"
  :page/logseq-is-having-a-problem "Logseq hat ein Problem festgestellt. Versuche zurückzukehren ..."
  :page/make-private "Privat machen"

+ 0 - 1
src/resources/dicts/en.edn

@@ -178,7 +178,6 @@
  :page/unfavorite "Unfavorite page"
  :page/show-journals "Show journals"
  :block/name "Page name"
- :page/earlier "Earlier"
  :page/copy-page-url "Copy page URL"
  :page/illegal-page-name "Illegal page name!"
  :page/page-already-exists "Page “{1}” already exists!"

+ 0 - 1
src/resources/dicts/es.edn

@@ -449,7 +449,6 @@
  :page/created-at                                   "Creada el"
  :page/delete                                       "Eliminar página"
  :page/delete-confirmation                          "¿Está seguro que desea eliminar esta página y su archivo?"
- :page/earlier                                      "Anteriormente"
  :page/illegal-page-name                            "¡Nombre de página ilegal!"
  :page/logseq-is-having-a-problem                   "Logseq está teniendo un problema. Para intentar volver a un estado de trabajo, intenta los siguientes pasos seguros en orden:"
  :page/make-private                                 "Hacer privada"

+ 0 - 1
src/resources/dicts/fa.edn

@@ -148,7 +148,6 @@
  :page/unfavorite "برداشتن از برگزیده‌ها"
  :page/show-journals "نمایش روزنگارها"
  :block/name "نام برگه"
- :page/earlier "پیش‌تر"
  :page/copy-page-url "رونوشت از نشانی برگه"
  :page/illegal-page-name "نام برگه غیرمجاز!"
  :page/page-already-exists "برگه «{1}» از پیش موجود است!"

+ 0 - 1
src/resources/dicts/fr.edn

@@ -156,7 +156,6 @@
     :page/backlinks "Rétro-lien"
     :page/copy-page-url "Copier l'URL de la page"
     :page/created-at "Créée le"
-    :page/earlier "Plus tôt"
     :page/open-backup-directory "Ouvrir le dossier de sauvegarde de la page"
     :page/open-in-finder "Ouvrir dans l'explorateur de fichiers"
     :page/open-with-default-app "Ouvrir avec l'application par défaut"

+ 0 - 1
src/resources/dicts/id.edn

@@ -167,7 +167,6 @@
  :page/unfavorite "Hapus dari Favorit"
  :page/show-journals "Tampilkan jurnal"
  :block/name "Nama Halaman"
- :page/earlier "Lebih awal"
  :page/copy-page-url "Salin URL halaman"
  :page/illegal-page-name "Nama halaman tidak sah!"
  :page/page-already-exists "Halaman “{1}” sudah ada!"

+ 0 - 1
src/resources/dicts/it.edn

@@ -58,7 +58,6 @@
  :page/unfavorite "Rimuovi la pagina dai Preferiti"
  :page/show-journals "Mostra diario"
  :block/name "Nome pagina"
- :page/earlier "Prima"
  :page/copy-page-url "Copia URL pagina"
  :file/name "Nome File"
  :file/last-modified-at "Ultima modifica alle"

+ 0 - 1
src/resources/dicts/ja.edn

@@ -176,7 +176,6 @@
  :page/unfavorite "お気に入りを解除"
  :page/show-journals "日誌を表示"
  :block/name "ページ名"
- :page/earlier "もっと前へ"
  :page/copy-page-url "ページの URL をコピー"
  :page/illegal-page-name "ページの名前が不正です"
  :page/page-already-exists "「{1}」というページは既に存在します!"

+ 0 - 1
src/resources/dicts/ko.edn

@@ -59,7 +59,6 @@
  :page/unfavorite "즐겨찾기에서 삭제"
  :page/show-journals "일지 보기"
  :block/name "페이지 이름"
- :page/earlier "이전"
  :page/copy-page-url "페이지 URL 복사"
  :file/name "파일 이름"
  :file/last-modified-at "마지막 편집 시간:"

+ 0 - 1
src/resources/dicts/nb-no.edn

@@ -61,7 +61,6 @@
  :page/unfavorite "Fjern side fra Faoritter"
  :page/show-journals "Vis Dagbøker"
  :block/name "Navn på siden"
- :page/earlier "Tidligere"
  :file/name "Filnavn"
  :file/last-modified-at "Sist endret"
  :file/no-data "Ingen data"

+ 0 - 1
src/resources/dicts/nl.edn

@@ -111,7 +111,6 @@
  :page/created-at "Aangemaakt op"
  :page/delete "Verwijder pagina"
  :page/delete-confirmation "Weet u zeker dat u deze pagina wilt verwijderen..."
- :page/earlier "Eerder"
  :page/make-private "Maak prive"
  :page/make-public "Maak publiek"
  :page/open-backup-directory "Open backups map pagina"

+ 0 - 1
src/resources/dicts/pl.edn

@@ -62,7 +62,6 @@
  :page/unfavorite "Usuń z ulubionych"
  :page/show-journals "Pokaż dzienniki"
  :block/name "Nazwa strony"
- :page/earlier "Wcześniej"
  :page/copy-page-url "Kopiuj adres URL strony"
  :file/name "Nazwa pliku"
  :file/last-modified-at "Ostatnio zmodyfikowany"

+ 0 - 1
src/resources/dicts/pt-br.edn

@@ -172,7 +172,6 @@
  :page/unfavorite "Remover dos favoritos"
  :page/show-journals "Mostrar diários"
  :block/name "Nome da página"
- :page/earlier "Anterior"
  :page/copy-page-url "Copiar URL da página"
  :page/illegal-page-name "Nome de página inválido!"
  :page/page-already-exists "Página “{1}” já existe!"

+ 0 - 1
src/resources/dicts/pt-pt.edn

@@ -79,7 +79,6 @@
  :page/unfavorite "Remover dos Favoritos"
  :page/show-journals "Mostrar Págs. Diárias"
  :block/name "Nome da página"
- :page/earlier "Antes"
  :page/copy-page-url "Copiar URL da página"
  :file/name "Nome do ficheiro"
  :file/last-modified-at "Última modificação em"

+ 0 - 1
src/resources/dicts/ru.edn

@@ -88,7 +88,6 @@
  :page/unfavorite                                      "Удалить из Избранного"
  :page/show-journals                                   "Показать журналы"
  :block/name                                           "Имя страницы"
- :page/earlier                                         "Ранее"
  :page/copy-page-url                                   "Копировать URL страницы"
  :page/illegal-page-name                               "Недопустимое название страницы!"
  :page/page-already-exists                             "Страница “{1}” уже существует!"

+ 0 - 1
src/resources/dicts/sk.edn

@@ -172,7 +172,6 @@
  :page/unfavorite                                  "Odstrániť z obľúbených"
  :page/show-journals                               "Zobraziť denníky"
  :block/name                                       "Názav stránky"
- :page/earlier                                     "Skôr"
  :page/copy-page-url                               "Kopírovať adresu stránky"
  :page/illegal-page-name                           "Neplatný názov stránky!"
  :page/page-already-exists                         "Stránka “{1}” už existuje!"

+ 0 - 1
src/resources/dicts/tr.edn

@@ -176,7 +176,6 @@
  :page/unfavorite "Sayfayı sık kullanılanlardan kaldır"
  :page/show-journals "Günlükleri göster"
  :block/name "Sayfa adı"
- :page/earlier "Daha önce"
  :page/copy-page-url "Sayfa URL adresini kopyala"
  :page/illegal-page-name "Geçersiz sayfa adı!"
  :page/page-already-exists "“{1}” sayfası zaten var!"

+ 0 - 1
src/resources/dicts/uk.edn

@@ -82,7 +82,6 @@
  :page/unfavorite "Вилучити сторінку з обраного"
  :page/show-journals "Показати журнали"
  :block/name "Назва сторінки"
- :page/earlier "Раніше"
  :page/copy-page-url "Скопіювати URL сторінки"
  :file/name "Назва файлу"
  :file/last-modified-at "Останнє модифіковано у "

+ 0 - 1
src/resources/dicts/zh-cn.edn

@@ -135,7 +135,6 @@
  :page/unfavorite "取消收藏"
  :page/show-journals "显示日志"
  :block/name "页面名称"
- :page/earlier "之前"
  :file/name "文件名"
  :file/last-modified-at "最后更改于"
  :file/no-data "没有数据"

+ 0 - 1
src/resources/dicts/zh-hant.edn

@@ -80,7 +80,6 @@
  :page/unfavorite "從我的最愛移除"
  :page/show-journals "顯示日記頁面"
  :block/name "頁面名稱"
- :page/earlier "最近"
  :page/copy-page-url "複製頁面連結"
  :file/name "檔案名稱"
  :file/last-modified-at "最後更新於"

+ 5 - 0
yarn.lock

@@ -6527,6 +6527,11 @@ [email protected]:
     loose-envify "^1.4.0"
     prop-types "^15.6.2"
 
+react-virtuoso@^4.7.11:
+  version "4.7.11"
+  resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.7.11.tgz#1bf97885aae6f140f53487b48ebe87c37c57def3"
+  integrity sha512-Kdn9qEtQI2ulEuBMzW2BTkDsfijB05QUd6lpZ1K36oyA3k65Cz4lG4EKrh2pCfUafX4C2uMSZOwzMOhbrMOTFA==
+
 [email protected]:
   version "17.0.2"
   resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"