浏览代码

Merge branch 'whiteboards' into enhance/whiteboards-tests

Konstantinos Kaloutas 3 年之前
父节点
当前提交
8c3bc8ad29

+ 5 - 3
.github/workflows/build-desktop-release.yml

@@ -122,9 +122,10 @@ jobs:
 
       - name: Set Build Environment Variables (only when workflow_dispath)
         if: ${{ github.event_name == 'workflow_dispatch' }}
+        # if scheduled, use default settings
         run: |
-          echo "ENABLE_PLUGINS=${{ github.event.inputs.enable-plugins }}" >> $GITHUB_ENV
-          echo "ENABLE_FILE_SYNC_PRODUCTION=${{ github.event.inputs.enable-file-sync-production }}" >> $GITHUB_ENV
+          echo "ENABLE_PLUGINS=${{ github.event_name == 'schedule' || github.event.inputs.enable-plugins == 'true' }}" >> $GITHUB_ENV
+          echo "ENABLE_FILE_SYNC_PRODUCTION=${{ github.event_name == 'schedule' || github.event.inputs.enable-file-sync-production == 'true' }}" >> $GITHUB_ENV
 
       - name: Compile CLJS
         run: yarn install && gulp build && yarn cljs:release-electron
@@ -426,7 +427,8 @@ jobs:
     if: ${{ github.event_name == 'schedule' || github.event.inputs.build-android == 'true' }}
     with:
       build-target: "${{ github.event.inputs.build-target }}"
-      enable-file-sync-production: "${{ github.event.inputs.enable-file-sync-production == 'true' }}"
+      # if scheduled, use production mode
+      enable-file-sync-production: "${{ github.event_name == 'schedule' || github.event.inputs.enable-file-sync-production == 'true' }}"
     secrets:
       ANDROID_KEYSTORE: "${{ secrets.ANDROID_KEYSTORE }}"
       ANDROID_KEYSTORE_PASSWORD: "${{ secrets.ANDROID_KEYSTORE_PASSWORD }}"

+ 6 - 5
src/electron/electron/url.cljs

@@ -8,16 +8,17 @@
 
 ;; Keep same as main/frontend.util.url
 (def decode js/decodeURI)
-(def decode-param js/decodeURIComponent)
 
 (defn get-URL-decoded-params
   "Get decoded URL parameters from parsed js/URL.
-   `nil` for non-existing keys."
-  [^js parsed-url keys]
+   `nil` for non-existing keys.
+   URL.searchParams are already decoded:
+   https://developer.mozilla.org/en-US/docs/Web/API/URL/searchParams"
+  [^js/URL parsed-url keys]
   (let [params (.-searchParams parsed-url)]
     (map (fn [key]
            (when-let [value (.get params key)]
-             (decode-param value)))
+             value))
          keys)))
 
 (defn graph-identifier-error-handler
@@ -59,7 +60,7 @@
 
 (defn- x-callback-url-handler
   "win - a window used for fallback (main window is prefered)"
-  [^js win parsed-url]
+  [^js win ^js/URL parsed-url]
   (let [action (.-pathname parsed-url)]
     (cond
       (= action "/quickCapture")

+ 2 - 2
src/main/frontend/commands.cljs

@@ -237,8 +237,8 @@
 
        ["Upload an asset" [[:editor/click-hidden-file-input :id]] "Upload file types like image, pdf, docx, etc.)"]
 
-       (state/deprecated-logged?)
-       ["Upload an image" [[:editor/click-hidden-file-input :id]]])]
+       ;; ["Upload an image" [[:editor/click-hidden-file-input :id]]]
+       )]
 
     (markdown-headings)
 

+ 1 - 1
src/main/frontend/dicts.cljc

@@ -4247,7 +4247,7 @@
         :settings "Ayarlar"
         :settings-of-plugins "Eklenti ayarları"
         :plugins "Eklentiler"
-        :themes "Temelar"
+        :themes "Temalar"
         :developer-mode-alert "Eklenti sistemini etkinleştirmek için uygulamayı yeniden başlatmanız gerekir. Şimdi yeniden başlatmak istiyor musunuz?"
         :relaunch-confirm-to-work "Çalışması için uygulama yeniden başlatılmalı. Şimdi yeniden başlatmak istiyor musunuz?"
         :import "İçeri aktar"

+ 41 - 48
src/main/frontend/fs/sync.cljs

@@ -37,7 +37,6 @@
 ;; - logseq/version-files
 ;;   downloaded version-files
 ;; files included by `get-ignored-files` will not be synchronized.
-;; files in these `get-monitored-dirs` dirs will be synchronized.
 ;;
 ;; sync strategy:
 ;; - when toggle file-sync on,
@@ -153,23 +152,22 @@
 
 ;;; ### configs in config.edn
 ;; - :file-sync/ignore-files
-;; - :file-sync/monitor-dirs
 
 (defn- get-ignored-files
   []
   (into #{#"logseq/graphs-txid.edn$"
-          #"logseq/\.recycle/.*"
-          #"logseq/version-files/.*"
-          #"logseq/bak/.*"}
+          #"logseq/version-files/"
+          #"logseq/bak/"
+          #"node_modules/"
+          ;; path starts with `.` in the root directory, e.g. .gitignore
+          #"^\.[^.]+"
+          ;; path includes `/.`, e.g. .git, .DS_store
+          #"/\."
+          ;; Emacs/Vim backup files end with `~` by default
+          #"~$"}
         (map re-pattern)
         (:file-sync/ignore-files (state/get-config))))
 
-(defn- get-monitor-dirs
-  []
-  (into #{#"^assets/" #"^journals/" #"^logseq/" #"^pages/" #"^draws/" #"^whiteboards/"}
-        (map #(re-pattern (str "^" % "/")))
-        (:file-sync/monitor-dirs (state/get-config))))
-
 ;;; ### configs ends
 
 (def ws-addr config/WS-URL)
@@ -354,9 +352,6 @@
                "\" (updated? " updated? ", renamed? " (.renamed? coll) ", deleted? " deleted?
                ", txid " txid ", checksum " checksum ")]")))
 
-(defn- contains-path? [regexps path]
-  (reduce #(when (re-find %2 path) (reduced true)) false regexps))
-
 (defn- assert-filetxns
   [filetxns]
   (every? true?
@@ -441,16 +436,16 @@
             (map list ts))))
    cat))
 
-(defn- filter-filetxns-by-config
-  "return transducer.
-  filter filetxns by `get-ignored-files` and `get-monitored-dirs`"
-  []
-  (let [ignored-files (get-ignored-files)
-        monitored-dirs (get-monitor-dirs)]
-    (filter
-     #(let [path (relative-path %)]
-        (and (contains-path? monitored-dirs path)
-             (not (contains-path? ignored-files path)))))))
+(defn- contains-path? [regexps path]
+  (reduce #(when (re-find %2 path) (reduced true)) false regexps))
+
+(defn ignored?
+  "Whether file is ignored when syncing."
+  [path]
+  (->
+   (get-ignored-files)
+   (contains-path? (relative-path path))
+   (boolean)))
 
 (defn- diffs->partitioned-filetxns
   "transducer.
@@ -465,7 +460,7 @@
   (comp
    (map diff->filetxns)
    cat
-   (filter-filetxns-by-config)
+   (remove ignored?)
    distinct-update-filetxns-xf
    remove-deleted-filetxns-xf
    (partition-filetxns n)))
@@ -1549,15 +1544,15 @@
   [type {:keys [dir path _content stat] :as _payload}]
   (when-let [current-graph (state/get-current-repo)]
     (when (string/ends-with? current-graph dir)
-      (when-not (some-> (state/get-file-sync-state current-graph)
-                        sync-state--stopped?)
-        (when (or (:mtime stat) (= type "unlink"))
-          (go
-            (let [path (remove-dir-prefix dir path)
-                  files-meta (and (not= "unlink" type)
-                                  (<! (<get-local-files-meta rsapi "" dir [path])))
-                  checksum (and (coll? files-meta) (some-> files-meta first :etag))]
-              (>! local-changes-chan (->FileChangeEvent type dir path stat checksum)))))))))
+      (let [sync-state (state/get-file-sync-state current-graph)]
+        (when (and sync-state (not (sync-state--stopped? sync-state)))
+          (when (or (:mtime stat) (= type "unlink"))
+            (go
+              (let [path (remove-dir-prefix dir path)
+                    files-meta (and (not= "unlink" type)
+                                    (<! (<get-local-files-meta rsapi "" dir [path])))
+                    checksum (and (coll? files-meta) (some-> files-meta first :etag))]
+                (>! local-changes-chan (->FileChangeEvent type dir path stat checksum))))))))))
 
 (defn local-changes-revised-chan-builder
   "return chan"
@@ -1981,7 +1976,9 @@
       add-history? (update :history add-history-items paths now))))
 
 (defn sync-state--stopped?
+  "Graph syncing is stopped"
   [sync-state]
+  {:pre [(s/valid? ::sync-state sync-state)]}
   (= ::stop (:state sync-state)))
 
 ;;; ### remote->local syncer & local->remote syncer
@@ -2172,8 +2169,7 @@
                    true)
                  (or (string/starts-with? (.-dir e) base-path)
                      (string/starts-with? (str "file://" (.-dir e)) base-path)) ; valid path prefix
-                 (not (contains-path? (get-ignored-files) (relative-path e))) ;not ignored
-                 (contains-path? (get-monitor-dirs) (relative-path e)) ; dir is monitored
+                 (not (ignored? e)) ;not ignored
                  ;; download files will also trigger file-change-events, ignore them
                  (let [r (not (contains? (:recent-remote->local-files @*sync-state)
                                          (<! (<file-change-event=>recent-remote->local-file-item e))))]
@@ -2220,10 +2216,9 @@
       (if (empty? es)
         (go {:succ true})
         (let [type          (.-type ^FileChangeEvent (first es))
-              ignored-files (get-ignored-files)
               es->paths-xf  (comp
                              (map #(relative-path %))
-                             (filter #(not (contains-path? ignored-files %))))]
+                             (remove ignored?))]
           (go
             (let [es*   (<! (<filter-checksum-not-consistent es))
                   _     (when (not= (count es*) (count es))
@@ -2295,18 +2290,13 @@
             (let [remote-all-files-meta remote-all-files-meta-or-exp
                   local-all-files-meta  (<! local-all-files-meta-c)
                   diff-local-files      (diff-file-metadata-sets local-all-files-meta remote-all-files-meta)
-                  monitored-dirs        (get-monitor-dirs)
-                  ignored-files         (get-ignored-files)
                   change-events
                   (sequence
                    (comp
                     ;; convert to FileChangeEvent
                     (map #(->FileChangeEvent "change" base-path (.get-normalized-path ^FileMetadata %)
                                              {:size (:size %)} (:etag %)))
-                    ;; filter ignore-files & monitored-dirs
-                    (filter #(let [path (relative-path %)]
-                               (and (not (contains-path? ignored-files path))
-                                    (contains-path? monitored-dirs path)))))
+                    (remove ignored?))
                    diff-local-files)
                   change-events-partitions
                   (sequence
@@ -2724,10 +2714,13 @@
     (go
       ;; stop previous sync
       (<! (<sync-stop))
-      (when-some [sm (sync-manager-singleton current-user-uuid graph-uuid
-                                             (config/get-repo-dir repo) repo
-                                             txid *sync-state)]
-        (when (and repo (not (config/demo-graph? repo)))
+      (when (and user-uuid graph-uuid txid
+                 (user/logged-in?)
+                 repo
+                 (not (config/demo-graph? repo)))
+        (when-some [sm (sync-manager-singleton current-user-uuid graph-uuid
+                                               (config/get-repo-dir repo) repo
+                                               txid *sync-state)]
           ;; 1. if remote graph has been deleted, clear graphs-txid.edn
           ;; 2. if graphs-txid.edn's content isn't [user-uuid graph-uuid txid], clear it
           (if (not= 3 (count @graphs-txid))

+ 4 - 2
src/main/frontend/handler/file_sync.cljs

@@ -16,6 +16,9 @@
 
 (def refresh-file-sync-component (atom false))
 
+
+(defn get-current-graph-uuid [] (second @sync/graphs-txid))
+
 (defn enable-sync?
   []
   (or (state/enable-sync?)
@@ -58,7 +61,7 @@
 (defn <delete-graph
   [graph-uuid]
   (go
-    (when (= graph-uuid @sync/graphs-txid)
+    (when (= graph-uuid (get-current-graph-uuid))
       (<! (sync/<sync-stop)))
     (let [r (<! (sync/<delete-graph sync/remoteapi graph-uuid))]
       (if (instance? ExceptionInfo r)
@@ -159,7 +162,6 @@
                                                  >))]
             all-version-list))))))
 
-(defn get-current-graph-uuid [] (second @sync/graphs-txid))
 
 (def *wait-syncing-graph (atom nil))
 

+ 0 - 5
src/main/frontend/state.cljs

@@ -1071,11 +1071,6 @@
   []
   (:me @state))
 
-(defn deprecated-logged?
-  "Whether the user has logged in."
-  []
-  false)
-
 (defn set-db-restoring!
   [value]
   (set-state! :db/restoring? value))

+ 22 - 0
src/test/frontend/fs/sync_test.cljs

@@ -0,0 +1,22 @@
+(ns frontend.fs.sync-test
+  (:require [frontend.fs.sync :as sync]
+            [clojure.test :refer [deftest are]]))
+
+(deftest ignored?
+  []
+  (are [x y] (= y (sync/ignored? x))
+    ".git" true
+    ".gitignore" true
+    ".DS_store" true
+    "foo/.DS_store" true
+    "logseq/graphs-txid.edn" true
+    "logseq/version-files/1.md" true
+    "logseq/bak/1.md" true
+    "node_modules/test" true
+    "foo/node_modules/" true
+    "backup~" true
+    "foo/backup~" true
+    "foo/.test.md" true
+    "pages/test.md" false
+    "journals/2022_01_01.md" false
+    ))

+ 1 - 9
templates/config.edn

@@ -272,16 +272,8 @@
  ;;  :media "[[quick capture]] **{time}**: {url}"}
 
  ;; File sync options
-
- ;; In addition to those directories created by Logseq,
- ;; files specified in the `:file-sync/monitor-dirs` directories will be synchronized too.
- ;;
- ;; Directories created by Logseq include:
- ;; ["assets" "journals" "logseq" "pages" "draws"].
- :file-sync/monitor-dirs []
-
  ;; Ignore these files when syncing, regexp is supported.
- :file-sync/ignore-files [".DS_Store$"]
+ ;; :file-sync/ignore-files []
 
  ;; dwim (do what I mean) for Enter key when editing.
  ;; Context-awareness of Enter key makes editing more easily

+ 1 - 10
tldraw/apps/tldraw-logseq/src/lib/tools/LogseqPortalTool/LogseqPortalTool.tsx

@@ -1,6 +1,5 @@
 import { TLApp, TLEvents, TLTool } from '@tldraw/core'
 import type { TLReactEventMap } from '@tldraw/react'
-import Vec from '@tldraw/vec'
 import { type Shape, LogseqPortalShape } from '../../shapes'
 import { CreatingState, IdleState } from './states'
 
@@ -16,15 +15,7 @@ export class LogseqPortalTool extends TLTool<
 
   Shape = LogseqPortalShape
 
-  private pinchCamera(point: number[], delta: number[], zoom: number) {
-    const { camera } = this.app.viewport
-    const nextPoint = Vec.sub(camera.point, Vec.div(delta, camera.zoom))
-    const p0 = Vec.sub(Vec.div(point, camera.zoom), nextPoint)
-    const p1 = Vec.sub(Vec.div(point, zoom), nextPoint)
-    this.app.setCamera(Vec.toFixed(Vec.add(nextPoint, Vec.sub(p1, p0))), zoom)
-  }
-
   onPinch: TLEvents<Shape>['pinch'] = info => {
-    this.pinchCamera(info.point, [0, 0], info.offset[0])
+    this.app.viewport.pinchCamera(info.point, [0, 0], info.offset[0])
   }
 }

+ 20 - 12
tldraw/packages/core/src/lib/TLViewport.ts

@@ -82,22 +82,30 @@ export class TLViewport {
     return Vec.mul(Vec.add(point, camera.point), camera.zoom)
   }
 
-  zoomIn = (): this => {
-    const { camera, bounds } = this
-    const zoom: number = Math.min(TLViewport.maxZoom, camera.zoom / ZOOM_UPDATE_FACTOR)
+  pinchCamera = (point: number[], delta: number[], zoom: number): this => {
+    const { camera } = this
+    zoom = Math.max(TLViewport.minZoom, Math.min(TLViewport.maxZoom, zoom));
+    const nextPoint = Vec.sub(camera.point, Vec.div(delta, camera.zoom))
+    const p0 = Vec.sub(Vec.div(point, camera.zoom), nextPoint)
+    const p1 = Vec.sub(Vec.div(point, zoom), nextPoint)
+    return this.update({ point: Vec.toFixed(Vec.add(nextPoint, Vec.sub(p1, p0))), zoom })
+  }
+
+  setZoom = (zoom: number) => {
+    const { bounds } = this
     const center = [bounds.width / 2, bounds.height / 2]
-    const p0 = Vec.sub(Vec.div(center, camera.zoom), center)
-    const p1 = Vec.sub(Vec.div(center, zoom), center)
-    return this.update({ point: Vec.toFixed(Vec.add(camera.point, Vec.sub(p1, p0))), zoom })
+    this.pinchCamera(center, [0, 0], zoom)
   }
 
-  zoomOut = (): this => {
+  zoomIn = () => {
+    const { camera } = this
+    this.setZoom(camera.zoom / ZOOM_UPDATE_FACTOR)
+  }
+
+  zoomOut = () => {
     const { camera, bounds } = this
-    const zoom: number = Math.max(TLViewport.minZoom, camera.zoom * ZOOM_UPDATE_FACTOR)
-    const center = [bounds.width / 2, bounds.height / 2]
-    const p0 = Vec.sub(Vec.div(center, camera.zoom), center)
-    const p1 = Vec.sub(Vec.div(center, zoom), center)
-    return this.update({ point: Vec.toFixed(Vec.add(camera.point, Vec.sub(p1, p0))), zoom })
+    this.setZoom(camera.zoom * ZOOM_UPDATE_FACTOR)
+
   }
 
   resetZoom = (): this => {

+ 1 - 10
tldraw/packages/core/src/lib/tools/TLMoveTool/states/PinchingState.ts

@@ -1,4 +1,3 @@
-import { Vec } from '@tldraw/vec'
 import type { TLEventMap, TLEventInfo, TLEvents } from '../../../../types'
 import type { TLShape } from '../../../shapes'
 import type { TLApp } from '../../../TLApp'
@@ -26,21 +25,13 @@ export class PinchingState<
 
   private prevDelta: number[] = [0, 0]
 
-  private pinchCamera(point: number[], delta: number[], zoom: number) {
-    const { camera } = this.app.viewport
-    const nextPoint = Vec.sub(camera.point, Vec.div(delta, camera.zoom))
-    const p0 = Vec.sub(Vec.div(point, camera.zoom), nextPoint)
-    const p1 = Vec.sub(Vec.div(point, zoom), nextPoint)
-    this.app.setCamera(Vec.toFixed(Vec.add(nextPoint, Vec.sub(p1, p0))), zoom)
-  }
-
   onEnter = (info: GestureInfo<S, K>) => {
     this.prevDelta = info.info.delta
     this.origin = info.info.point
   }
 
   onPinch: TLEvents<S>['pinch'] = info => {
-    this.pinchCamera(info.point, [0, 0], info.offset[0])
+    this.app.viewport.pinchCamera(info.point, [0, 0], info.offset[0])
   }
 
   onPinchEnd: TLEvents<S>['pinch'] = () => {

+ 29 - 9
tldraw/packages/core/src/lib/tools/TLSelectTool/states/PinchingState.ts

@@ -1,4 +1,3 @@
-import { Vec } from '@tldraw/vec'
 import type { TLEventMap, TLEventInfo, TLEvents } from '../../../../types'
 import type { TLShape } from '../../../shapes'
 import type { TLApp } from '../../../TLApp'
@@ -22,16 +21,14 @@ export class PinchingState<
 > extends TLToolState<S, K, R, P> {
   static id = 'pinching'
 
-  private pinchCamera(point: number[], delta: number[], zoom: number) {
+  onPinch: TLEvents<S>['pinch'] = (info, event: any) => {
     const { camera } = this.app.viewport
-    const nextPoint = Vec.sub(camera.point, Vec.div(delta, camera.zoom))
-    const p0 = Vec.sub(Vec.div(point, camera.zoom), nextPoint)
-    const p1 = Vec.sub(Vec.div(point, zoom), nextPoint)
-    this.app.setCamera(Vec.toFixed(Vec.add(nextPoint, Vec.sub(p1, p0))), zoom)
-  }
 
-  onPinch: TLEvents<S>['pinch'] = info => {
-    this.pinchCamera(info.point, [0, 0], info.offset[0])
+    // Normalize the value of deltaZ from raw WheelEvent
+    const deltaZ = normalizeWheel(event)[2] * 0.01
+    if (deltaZ === 0) return;
+    const zoom = camera.zoom - deltaZ * camera.zoom;
+    this.app.viewport.pinchCamera(info.point, [0, 0], zoom)
   }
 
   onPinchEnd: TLEvents<S>['pinch'] = () => {
@@ -42,3 +39,26 @@ export class PinchingState<
     this.tool.transition('idle')
   }
 }
+
+// Adapted from https://stackoverflow.com/a/13650579
+function normalizeWheel(event: WheelEvent) {
+  const MAX_ZOOM_STEP = 10
+  const { deltaY, deltaX } = event
+
+  let deltaZ = 0
+
+  if (event.ctrlKey || event.metaKey) {
+    const signY = Math.sign(event.deltaY)
+    const absDeltaY = Math.abs(event.deltaY)
+
+    let dy = deltaY
+
+    if (absDeltaY > MAX_ZOOM_STEP) {
+      dy = MAX_ZOOM_STEP * signY
+    }
+
+    deltaZ = dy
+  }
+
+  return [deltaX, deltaY, deltaZ]
+}