mirror of https://github.com/logseq/logseq
Merge branch 'whiteboards' into enhance/whiteboards-tests
commit
8c3bc8ad29
|
@ -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 }}"
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
))
|
|
@ -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,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])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
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 })
|
||||
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 })
|
||||
}
|
||||
|
||||
zoomOut = (): this => {
|
||||
const { camera, bounds } = this
|
||||
const zoom: number = Math.max(TLViewport.minZoom, camera.zoom * ZOOM_UPDATE_FACTOR)
|
||||
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)
|
||||
}
|
||||
|
||||
zoomIn = () => {
|
||||
const { camera } = this
|
||||
this.setZoom(camera.zoom / ZOOM_UPDATE_FACTOR)
|
||||
}
|
||||
|
||||
zoomOut = () => {
|
||||
const { camera, bounds } = this
|
||||
this.setZoom(camera.zoom * ZOOM_UPDATE_FACTOR)
|
||||
|
||||
}
|
||||
|
||||
resetZoom = (): this => {
|
||||
|
|
|
@ -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'] = () => {
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue