Merge branch 'master' into feat/db

This commit is contained in:
Tienson Qin
2025-05-13 18:22:20 +08:00
39 changed files with 6657 additions and 2858 deletions

View File

@@ -42,7 +42,7 @@ on:
env:
CLOJURE_VERSION: '1.11.1.1413'
NODE_VERSION: '20'
NODE_VERSION: '22'
JAVA_VERSION: '17'
jobs:

View File

@@ -19,7 +19,7 @@ on:
env:
CLOJURE_VERSION: '1.11.1.1413'
NODE_VERSION: '20'
NODE_VERSION: '22'
JAVA_VERSION: '17'
jobs:

View File

@@ -48,7 +48,7 @@ on:
env:
CLOJURE_VERSION: '1.11.1.1413'
NODE_VERSION: '20'
NODE_VERSION: '22'
JAVA_VERSION: '11'
jobs:
@@ -307,6 +307,8 @@ jobs:
- name: Build/Release Electron app
run: yarn electron:make
working-directory: ./static
env:
DEBUG: electron-packager
#env:
# CODE_SIGN_CERTIFICATE_FILE: ../codesign.pfx
# CODE_SIGN_CERTIFICATE_PASSWORD: ${{ secrets.CODE_SIGN_CERTIFICATE_PASSWORD }}
@@ -393,7 +395,7 @@ jobs:
# key: ${{ runner.os }}-node-modules
- name: Build/Release Electron App for x64
run: yarn install && yarn electron:make
run: yarn install && yarn rebuild:all && yarn electron:make
working-directory: ./static
env:
APPLE_ID: ${{ secrets.APPLE_ID_EMAIL }}
@@ -466,7 +468,7 @@ jobs:
# key: ${{ runner.os }}-node-modules
- name: Fetch deps and fix dugit arch for arm64
run: yarn install --ignore-platform && cd node_modules/dugite && npm_config_arch=arm64 node script/download-git.js
run: yarn install --ignore-platform && yarn rebuild:all && cd node_modules/dugite && npm_config_arch=arm64 node script/download-git.js
working-directory: ./static
- name: Build/Release Electron App for arm64
@@ -507,6 +509,9 @@ jobs:
needs: [ build-windows ]
runs-on: [self-hosted, macos, token]
steps:
- name: Remove old builds
run: rm -rf ./builds && mkdir ./builds
- name: Download Windows Artifact
uses: actions/download-artifact@v4
with:

View File

@@ -12,7 +12,7 @@ on:
env:
CLOJURE_VERSION: '1.11.1.1413'
NODE_VERSION: '20'
NODE_VERSION: '22'
JAVA_VERSION: '11'
jobs:

View File

@@ -17,7 +17,7 @@ on:
env:
CLOJURE_VERSION: '1.11.1.1413'
NODE_VERSION: '20'
NODE_VERSION: '22'
JAVA_VERSION: '11'
jobs:

View File

@@ -19,7 +19,7 @@ on:
env:
CLOJURE_VERSION: '1.11.1.1413'
NODE_VERSION: '20'
NODE_VERSION: '22'
JAVA_VERSION: '17'
jobs:

View File

@@ -14,7 +14,7 @@ env:
CLOJURE_VERSION: '1.11.1.1413'
JAVA_VERSION: '11'
# This is the latest node version we can run.
NODE_VERSION: '20'
NODE_VERSION: '22'
BABASHKA_VERSION: '1.0.168'
jobs:

View File

@@ -23,7 +23,7 @@ env:
CLOJURE_VERSION: '1.11.1.1413'
JAVA_VERSION: '11'
# This is the latest node version we can run.
NODE_VERSION: '20'
NODE_VERSION: '22'
BABASHKA_VERSION: '1.0.168'
jobs:

View File

@@ -19,7 +19,7 @@ env:
CLOJURE_VERSION: '1.11.1.1413'
JAVA_VERSION: '11'
# This is the latest node version we can run.
NODE_VERSION: '20'
NODE_VERSION: '22'
BABASHKA_VERSION: '1.0.168'
jobs:

View File

@@ -28,7 +28,7 @@ env:
# This is the same as 1.8.
JAVA_VERSION: '11'
# This is the latest node version we can run.
NODE_VERSION: '20'
NODE_VERSION: '22'
BABASHKA_VERSION: '1.0.168'
jobs:

View File

@@ -23,7 +23,7 @@ env:
CLOJURE_VERSION: '1.11.1.1413'
JAVA_VERSION: '11'
# This is the latest node version we can run.
NODE_VERSION: '20'
NODE_VERSION: '22'
BABASHKA_VERSION: '1.0.168'
jobs:

View File

@@ -28,7 +28,7 @@ env:
# This is the same as 1.8.
JAVA_VERSION: '11'
# This is the latest node version we can run.
NODE_VERSION: '20'
NODE_VERSION: '22'
BABASHKA_VERSION: '1.0.168'
jobs:

View File

@@ -63,7 +63,6 @@
(re-find #"(?i)^(COM[0-9]|CON|LPT[0-9]|NUL|PRN|AUX|com[0-9]|con|lpt[0-9]|nul|prn|aux)\..+" fname)
(re-find #"[\u0000-\u001f\u0080-\u009f]" fname)))))
(defn- path-join-internal
"Joins the given path segments into a single path, handling relative paths,
'..' and '.' normalization."
@@ -153,7 +152,6 @@
encoded-new-path (apply uri-path-join-internal path segments)]
(str scheme "//" domain encoded-new-path)))
(defn path-join
"Join path segments, or URL base and path segments"
[base & segments]
@@ -191,13 +189,11 @@
:else
(path-join (str protocol "//") path)))
(defn- path-normalize-internal
"Normalize path using path-join, break into segment and re-join"
[path]
(path-join path))
(defn url-normalize
[origin-url]
(let [^js url (js/URL. origin-url)
@@ -223,7 +219,13 @@
(if (is-file-url? original-url)
;; NOTE: URL type is not consistent across all protocols
;; Check file:// and assets://, pathname behavior is different
(let [^js url (js/URL. (string/replace original-url "assets://" "file://"))
(let [^js url (try
(js/URL. (string/replace (safe-decode-uri-component original-url) "assets://" "file://"))
(catch :default e
(js/console.error "invalid URL:"
(str "original-url: " original-url
" url: " (string/replace (safe-decode-uri-component original-url) "assets://" "file://")))
(throw e)))
path (safe-decode-uri-component (.-pathname url))
host (.-host url)
path (if (string/starts-with? path "///")
@@ -276,7 +278,6 @@
(safe-decode-uri-component (str base-prefix (string/join "/" remain-segs)))
(str base-prefix (string/join "/" remain-segs)))))))
(defn parent
"Parent, containing directory"
[path]
@@ -285,7 +286,6 @@
(path-normalize (str path "/.."))
nil))
(defn resolve-relative-path
"Assume current-path is a file"
[current-path rel-path]

View File

@@ -208,7 +208,6 @@
[?h :block/marker ?marker]
[(contains? #{"NOW" "DOING"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
[?p :block/journal-day ?d]
[(>= ?d ?start)]
[(<= ?d ?today)]]
@@ -225,7 +224,6 @@
[?h :block/marker ?marker]
[(contains? #{"NOW" "LATER" "TODO"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
[?p :block/journal-day ?d]
[(> ?d ?start)]
[(< ?d ?next)]]

View File

@@ -131,7 +131,7 @@
"d3-force": "3.0.0",
"diff": "5.0.0",
"dompurify": "2.4.0",
"electron": "35.0.1",
"electron": "36.2.0",
"electron-dl": "^4.0.0",
"emoji-mart": "^5.5.2",
"fs": "0.0.1-security",

View File

@@ -5,7 +5,7 @@ module.exports = {
packagerConfig: {
name: 'Logseq',
icon: './icons/logseq_big_sur.icns',
buildVersion: 84,
buildVersion: "85",
protocols: [
{
"protocol": "logseq",

View File

@@ -107,51 +107,6 @@ contextBridge.exposeInMainWorld('apis', {
)
},
/**
* When from is empty. The resource maybe from
* client paste or screenshoot.
* @param repoPathRoot
* @param to
* @param from?
* @returns {Promise<void>}
*/
async copyFileToAssets (repoPathRoot, to, from) {
if (from && fs.statSync(from).isDirectory()) {
throw new Error('not support copy directory')
}
const dest = path.join(repoPathRoot, to)
const assetsRoot = path.dirname(dest)
await fs.promises.mkdir(assetsRoot, { recursive: true })
from = from || getFilePathFromClipboard()
if (from) {
try {
// console.debug('copy file: ', from, dest)
await fs.promises.copyFile(from, dest)
return path.basename(from)
} catch (e) {
from = decodeURIComponent(from)
await fs.promises.copyFile(from, dest)
return path.basename(from)
}
}
// support image
// console.debug('read image: ', from, dest)
const nImg = clipboard.readImage()
if (nImg && !nImg.isEmpty()) {
const rawExt = path.extname(dest)
return await fs.promises.writeFile(
dest.replace(rawExt, '.png'),
nImg.toPNG()
)
}
},
toggleMaxOrMinActiveWindow (isToggleMin = false) {
ipcRenderer.invoke('toggle-max-or-min-active-win', isToggleMin)
},

View File

@@ -14,14 +14,14 @@
"electron:make-linux-arm64": "electron-forge make --platform=linux --arch=arm64",
"electron:make-macos-arm64": "electron-forge make --platform=darwin --arch=arm64",
"electron:publish:github": "electron-forge publish",
"rebuild:all": "electron-rebuild -v 35.0.1 -f",
"rebuild:all": "electron-rebuild -v 36.2.0 -f",
"postinstall": "install-app-deps"
},
"config": {
"forge": "./forge.config.js"
},
"dependencies": {
"@fastify/cors": "10.0.1",
"@fastify/cors": "11.0.1",
"@logseq/rsapi": "0.0.91",
"@sentry/electron": "2.5.1",
"abort-controller": "3.0.0",
@@ -35,7 +35,7 @@
"electron-squirrel-startup": "1.0.0",
"electron-window-state": "5.0.3",
"extract-zip": "2.0.1",
"fastify": "5.1.0",
"fastify": "5.3.2",
"fs-extra": "9.1.0",
"https-proxy-agent": "7.0.2",
"node-fetch": "2.6.7",
@@ -46,22 +46,22 @@
"update-electron-app": "2.0.1"
},
"devDependencies": {
"@electron-forge/cli": "^7.3.1",
"@electron-forge/maker-deb": "^7.3.1",
"@electron-forge/maker-dmg": "^7.3.1",
"@electron-forge/maker-wix": "^7.3.1",
"@electron-forge/maker-rpm": "^7.3.1",
"@electron-forge/maker-squirrel": "^7.3.1",
"@electron-forge/maker-zip": "^7.3.1",
"@electron/rebuild": "3.2.10",
"electron": "35.0.1",
"electron-builder": "25.1.8",
"@electron-forge/cli": "^7.8.0",
"@electron-forge/maker-deb": "^7.8.0",
"@electron-forge/maker-dmg": "^7.8.0",
"@electron-forge/maker-wix": "^7.8.0",
"@electron-forge/maker-rpm": "^7.8.0",
"@electron-forge/maker-squirrel": "^7.8.0",
"@electron-forge/maker-zip": "^7.8.0",
"@electron/rebuild": "4.0.1",
"electron": "36.2.0",
"electron-builder": "26.0.12",
"electron-forge-maker-appimage": "https://github.com/logseq/electron-forge-maker-appimage.git",
"electron-devtools-installer": "^3.2.0"
},
"resolutions": {
"**/electron": "35.0.1",
"**/node-abi": "3.74.0",
"**/electron": "36.2.0",
"**/node-abi": "3.75.0",
"**/node-gyp": "11.1.0",
"string-width": "4.2.0",
"wrap-ansi": "^7.0.0",

View File

@@ -458,7 +458,7 @@
(let [repo (state/get-current-repo)
file-rpath (string/replace s #"^[.\/\\]*assets[\/\\]+" "assets/")
dir (config/get-repo-dir repo)]
(-> (fs/write-file! repo dir file-rpath content nil)
(-> (fs/write-plain-text-file! repo dir file-rpath content nil)
(p/then load$)))))
(js/console.error _e)))))))

View File

@@ -345,7 +345,7 @@
parent-dir (path/path-join repo-dir (path/dirname (:path file)))]
(p/do!
(fs/mkdir-if-not-exists parent-dir)
(fs/write-file! repo repo-dir (:path file) content {:skip-transact? true})))))))
(fs/write-plain-text-file! repo repo-dir (:path file) content {:skip-transact? true})))))))
(defn- import-file-graph
[*files

View File

@@ -216,7 +216,7 @@
(let [repo-cur (state/get-current-repo)
repo-dir (config/get-repo-dir repo-cur)
data (with-out-str (pprint {:highlights highlights :extra extra}))]
(fs/write-file! repo-cur repo-dir hls-file data {:skip-compare? true}))))
(fs/write-plain-text-file! repo-cur repo-dir hls-file data {:skip-compare? true}))))
(defn file-based-resolve-hls-data-by-key$
[target-key]
@@ -242,7 +242,7 @@
new-fpath (str fdir "/" fname "_" fstamp ".png")
old-fpath (and old-fstamp (str fdir "/" fname "_" old-fstamp ".png"))
_ (and old-fpath (fs/rename! repo-url old-fpath new-fpath))
_ (fs/write-file! repo-url repo-dir new-fpath png {:skip-compare? true})]
_ (fs/write-plain-text-file! repo-url repo-dir new-fpath png {:skip-compare? true})]
(js/console.timeEnd :write-area-image)))

View File

@@ -2,21 +2,21 @@
"System-component-like ns that provides common file operations for all
platforms by delegating to implementations of the fs protocol"
(:require [cljs-bean.core :as bean]
[clojure.string :as string]
[electron.ipc :as ipc]
[frontend.config :as config]
[frontend.fs.nfs :as nfs]
[frontend.fs.node :as node]
[frontend.fs.capacitor-fs :as capacitor-fs]
[frontend.fs.memory-fs :as memory-fs]
[frontend.mobile.util :as mobile-util]
[frontend.fs.nfs :as nfs]
[frontend.fs.node :as node]
[frontend.fs.protocol :as protocol]
[frontend.mobile.util :as mobile-util]
[frontend.state :as state]
[frontend.util :as util]
[lambdaisland.glogi :as log]
[promesa.core :as p]
[logseq.common.path :as path]
[clojure.string :as string]
[frontend.state :as state]
[logseq.common.util :as common-util]
[electron.ipc :as ipc]))
[promesa.core :as p]))
(defonce nfs-backend (nfs/->Nfs))
(defonce memory-backend (memory-fs/->MemoryFs))
@@ -99,8 +99,8 @@
(when (= fs memory-backend)
(protocol/rmdir! fs dir))))
;; TODO(andelf): distinguish from graph file writing and global file write
(defn write-file!
(defn write-plain-text-file!
"Use it only for plain-text files, not binary"
[repo dir rpath content opts]
(when content
(let [path (common-util/path-normalize rpath)
@@ -182,8 +182,6 @@
(p/let [_ (mkdir-if-not-exists new-dir)]
(protocol/copy! (get-fs old-path) repo old-path new-path)))))
(defn open-dir
[dir]
(let [record (get-native-backend)]
@@ -227,7 +225,7 @@
true)
(p/catch
(fn [_error]
(p/let [_ (write-file! repo dir path initial-content nil)]
(p/let [_ (write-plain-text-file! repo dir path initial-content nil)]
false))))))
(defn file-exists?

View File

@@ -3,17 +3,17 @@
(:require ["@capacitor/filesystem" :refer [Encoding Filesystem]]
[cljs-bean.core :as bean]
[clojure.string :as string]
[goog.string :as gstring]
[frontend.config :as config]
[frontend.db :as db]
[frontend.fs.protocol :as protocol]
[frontend.mobile.util :as mobile-util]
[frontend.state :as state]
[frontend.util :as util]
[goog.string :as gstring]
[lambdaisland.glogi :as log]
[logseq.common.path :as path]
[promesa.core :as p]
[rum.core :as rum]
[logseq.common.path :as path]))
[rum.core :as rum]))
(when (mobile-util/native-ios?)
(defn ios-ensure-documents!
@@ -41,18 +41,6 @@
(fn [_error]
false)))
(defn <write-file-with-base64
"Write a binary file, requires base64 encoding"
[path content]
(when-not (string/blank? path)
(-> (p/chain (.writeFile Filesystem (clj->js {:path path
:data content
:recursive true}))
#(js->clj % :keywordize-keys true))
(p/catch (fn [error]
(js/console.error "writeFile Error: " path ": " error)
nil)))))
(defn- <write-file-with-utf8
[path content]
(when-not (string/blank? path)

View File

@@ -164,8 +164,7 @@
:remote->local-full-sync-failed
:local->remote-full-sync-failed
:get-remote-graph-failed
:get-deletion-logs-failed
})
:get-deletion-logs-failed})
(s/def ::sync-event (s/keys :req-un [::event ::data]))
@@ -198,7 +197,6 @@
[x]
(when (instance? ExceptionInfo x) x))
(def ws-addr config/WS-URL)
;; Warning: make sure to `persist-var/-load` graphs-txid before using it.
@@ -560,7 +558,6 @@
(map-indexed filepath+checksum->diff)
(diffs->partitioned-filetxns n)))
(deftype FileMetadata [size etag path encrypted-path last-modified remote? txid ^:mutable normalized-path]
Object
(get-normalized-path [_]
@@ -596,13 +593,10 @@
:txid txid
not-found))
IPrintWithWriter
(-pr-writer [_ w _opts]
(write-all w (str {:size size :etag etag :path path :remote? remote? :txid txid :last-modified last-modified}))))
(def ^:private higher-priority-remote-files
"when diff all remote files and local files, following remote files always need to download(when checksum not matched),
even local-file's last-modified > remote-file's last-modified.
@@ -726,7 +720,6 @@
common-util/path-normalize)
;;; ### APIs
;; `RSAPI` call apis through rsapi package, supports operations on files
@@ -765,16 +758,13 @@
(<get-graph-encrypt-keys [this graph-uuid])
(<upload-graph-encrypt-keys [this graph-uuid public-key encrypted-private-key]))
(defprotocol IRemoteControlAPI
"api functions provided for outside the sync process"
(<delete-remote-files-control [this graph-uuid filepaths])
)
(<delete-remote-files-control [this graph-uuid filepaths]))
(defprotocol IToken
(<get-token [this]))
(defn <case-different-local-file-exist?
"e.g. filepath=\"pages/Foo.md\"
found-filepath=\"pages/foo.md\"
@@ -1138,12 +1128,10 @@
val (do (pp/pprint [:debug :sync-event val])
(recur))))))))
(defn stop-debug-print-sync-events-loop
[]
(offer! debug-print-sync-events-loop-stop-chan true))
;;; sync events ends
(defn- fire-file-sync-storage-exceed-limit-event!
@@ -1232,7 +1220,6 @@
(recur result-file-meta-list others))))
(vals (persistent! result-file-meta-list))))))
(extend-type RemoteAPI
IRemoteAPI
(<user-info [this]
@@ -1438,13 +1425,10 @@
(comment
(declare remoteapi)
(<delete-remote-files-control remoteapi (second @graphs-txid) ["pages/aa.md"])
)
(<delete-remote-files-control remoteapi (second @graphs-txid) ["pages/aa.md"]))
(def remoteapi (->RemoteAPI nil))
(def ^:private *get-graph-salt-memoize-cache (atom {}))
(defn update-graph-salt-cache [graph-uuid v]
{:pre [(map? v)
@@ -1521,9 +1505,6 @@
val val
timeout' (recur))))))
(defn- assert-local-txid<=remote-txid
[]
(when-let [local-txid (last @graphs-txid)]
@@ -1548,7 +1529,6 @@
sync-state--remove-recent-remote->local-files
sync-state--stopped?)
(defn- filetxns=>recent-remote->local-files
[filetxns]
(let [{:keys [update-filetxns delete-filetxns rename-filetxns]}
@@ -1610,7 +1590,7 @@
(fs/unlink! repo (path/path-join repo-dir base-file) {}))
;; base-content != current-content, merge, do not delete
(p/let [merged-content (diff-merge/three-way-merge base-content "" current-content format)]
(fs/write-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
(fs/write-plain-text-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
:from-disk? true
:fs/event :fs/remote-file-change}))))
@@ -1660,7 +1640,7 @@
merged-content (diff-merge/three-way-merge base-content incoming-content current-content format)]
(when (seq merged-content)
(p/do!
(fs/write-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
(fs/write-plain-text-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
:from-disk? true
:fs/event :fs/remote-file-change})))))))
@@ -1687,7 +1667,7 @@
;; else
(p/do!
(fs/write-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
(fs/write-plain-text-file! repo repo-dir current-change-file merged-content {:skip-compare? true})
(file-handler/alter-file repo current-change-file merged-content {:re-render-root? true
:from-disk? true
:fs/event :fs/remote-file-change})))))))))))))))))
@@ -1841,7 +1821,6 @@
[r]
(some->> (ex-cause r) str (re-find #"Request is not yet valid")))
;; type = "change" | "add" | "unlink"
(deftype FileChangeEvent [type dir path stat checksum]
IRelativePath
@@ -1876,7 +1855,6 @@
(-pr-writer [_ w _opts]
(write-all w (str {:type type :base-path dir :path path :size (:size stat) :checksum checksum}))))
(defn- <file-change-event=>recent-remote->local-file-item
"return nil when related local files not found"
[graph-uuid ^FileChangeEvent e]
@@ -2046,7 +2024,6 @@
(js/localStorage.removeItem k))
(reset! pwd-map {}))
(defn encrypt+persist-pwd!
"- persist encrypted pwd at local-storage"
[pwd graph-uuid]
@@ -2094,7 +2071,6 @@
(when (and private-key (string/starts-with? private-key "AGE-SECRET-KEY"))
(set-keys&notify graph-uuid public-key private-key)))))
(def <restored-pwd (chan (async/sliding-buffer 1)))
(def <restored-pwd-pub (async/pub <restored-pwd :graph-uuid))
@@ -2124,7 +2100,6 @@
(swap! pwd-map dissoc graph-uuid)
(remove-pwd! graph-uuid))
(defn- <loop-ensure-pwd&keys
[graph-uuid repo *stopped?]
(let [<restored-pwd-sub-chan (chan 1)]
@@ -2186,7 +2161,6 @@
(clear-pwd! graph-uuid)
(recur))))))))))
(defn- <set-env&keys
[prod? graph-uuid]
(let [{:keys [private-key public-key]} (get @pwd-map graph-uuid)]
@@ -2241,7 +2215,6 @@
(fn [_ _ _ _]
(offer! recent-edited-chan true)))
;;; ### sync state
(def *resume-state
@@ -2385,7 +2358,6 @@
(contains? #{::idle ::local->remote ::remote->local ::local->remote-full-sync ::remote->local-full-sync}
(:state sync-state)))
;;; ### remote->local syncer & local->remote syncer
(defprotocol IRemote->LocalSync
@@ -2866,8 +2838,7 @@
(or need-sync-remote graph-has-been-deleted unknown stop) r)))))]
;; update *txid-for-get-deletion-log
(reset! *txid-for-get-deletion-log @*txid)
r
)))))))
r)))))))
;;; ### put all stuff together
@@ -3276,7 +3247,6 @@
(reset! current-sm-graph-uuid graph-uuid)
(sync-manager user-uuid graph-uuid base-path repo txid *sync-state)))
(defn <sync-stop []
(go
(when-let [sm ^SyncManager (state/get-file-sync-manager (state/get-current-file-sync-graph-uuid))]
@@ -3347,7 +3317,6 @@
(when-let [graph-uuid (second @graphs-txid)]
(get-pwd graph-uuid)))
(defn- <connectivity-testing
[]
(go
@@ -3517,7 +3486,6 @@
(<sync-start))
(recur))
;;; ### some sync events handler
;; re-exec remote->local-full-sync when it failed before
@@ -3544,5 +3512,4 @@
;;; add-tap
(comment
(def *x (atom nil))
(add-tap (fn [v] (reset! *x v)))
)
(add-tap (fn [v] (reset! *x v))))

View File

@@ -266,7 +266,7 @@
repo-dir (config/get-repo-dir repo)
file-path (path/path-join common-config/local-assets-dir
(str asset-block-id-str "." asset-type))]
(fs/write-file! repo repo-dir file-path data {})))
(fs/write-plain-text-file! repo repo-dir file-path data {})))
(defn <unlink-asset
[repo asset-block-id asset-type]

View File

@@ -25,16 +25,18 @@
(let [path file
repo (state/get-current-repo)]
(when repo
(let [repo-dir (config/get-repo-dir repo)]
(->
(p/do!
(create-draws-directory! repo)
(fs/write-plain-text-file! repo repo-dir path data nil)
(db/transact! repo
[{:file/path path
:block/name (util/page-name-sanity-lc file)
:block/file {:file/path path}}]))
(p/catch (fn [error]
(prn "Write file failed, path: " path ", data: " data)
(js/console.dir error)))))))
(js/console.dir error))))))))
(defn load-excalidraw-file
[file ok-handler]

View File

@@ -3,6 +3,7 @@
[clojure.string :as string]
[clojure.walk :as w]
[dommy.core :as dom]
[electron.ipc :as ipc]
[frontend.commands :as commands]
[frontend.config :as config]
[frontend.date :as date]
@@ -16,7 +17,6 @@
[frontend.format.block :as block]
[frontend.format.mldoc :as mldoc]
[frontend.fs :as fs]
[frontend.fs.capacitor-fs :as capacitor-fs]
[frontend.handler.assets :as assets-handler]
[frontend.handler.block :as block-handler]
[frontend.handler.common :as common-handler]
@@ -46,7 +46,6 @@
[frontend.util.list :as list]
[frontend.util.text :as text-util]
[frontend.util.thingatpt :as thingatpt]
[goog.crypt.base64 :as base64]
[goog.dom :as gdom]
[goog.dom.classes :as gdom-classes]
[goog.object :as gobj]
@@ -1054,6 +1053,8 @@
(state/set-block-op-type! :cut)
(when-let [blocks (->> (get-selected-blocks)
(remove #(dom/has-class? % "property-value-container"))
(remove (fn [block] (or (= "true" (dom/attr block "data-query"))
(= "true" (dom/attr block "data-transclude")))))
seq)]
;; remove queries
(let [dom-blocks (remove (fn [block] (= "true" (dom/attr block "data-query"))) blocks)]
@@ -1382,8 +1383,6 @@
(property-file/remove-properties-when-file-based repo format)
string/trim)))
(def insert-command! editor-common-handler/insert-command!)
(defn delete-asset-of-block!
[{:keys [repo asset-block href full-text block-id local? delete-local?] :as _opts}]
(let [block (db-model/query-block-by-uuid block-id)
@@ -1407,36 +1406,16 @@
(path/resolve-relative-path block-file-rpath href)))]
(fs/unlink! repo asset-fpath nil)))))))
(defn- write-file!
[repo dir file file-rpath file-name]
(defn db-based-save-asset!
[repo dir file file-rpath]
(p/let [buffer (.arrayBuffer file)]
(if (util/electron?)
(if-let [from (not-empty (.-path file))]
(-> (js/window.apis.copyFileToAssets dir file-rpath from)
(p/catch #(js/console.error "Debug: Copy Asset Error#" %)))
(-> (p/let [buffer (.arrayBuffer file)]
(fs/write-file! repo dir file-rpath buffer {:skip-compare? false}))
(p/catch #(js/console.error "Debug: Writing Asset #" %))))
(->
(p/do! (js/console.debug "Debug: Writing Asset #" dir file-rpath)
(cond
(mobile-util/native-platform?)
;; capacitor fs accepts Blob, File implements Blob
(p/let [buffer (.arrayBuffer file)
content (base64/encodeByteArray (js/Uint8Array. buffer))
fpath (path/path-join dir file-rpath)]
(capacitor-fs/<write-file-with-base64 fpath content))
(config/db-based-graph? repo) ;; memory-fs
(ipc/ipc "writeFile" repo (path/path-join dir file-rpath) buffer)
;; web
(p/let [buffer (.arrayBuffer file)
content (js/Uint8Array. buffer)]
(fs/write-file! repo dir file-rpath content nil))
:else
(throw (ex-info "Paste failed"
{:file-name file-name}))))
(p/catch (fn [error]
(prn :paste-file-error)
(js/console.error error))))))
;; actually, writing binary using memory fs
(fs/write-plain-text-file! repo dir file-rpath content nil)))))
(defn db-based-save-assets!
"Save incoming(pasted) assets to assets directory.
@@ -1470,7 +1449,7 @@
insert-opts {:custom-uuid block-id
:edit-block? false
:properties properties}
_ (write-file! repo dir file file-rpath file-name)
_ (db-based-save-asset! repo dir file file-rpath)
edit-block (state/get-edit-block)
insert-to-current-block-page? (and (:block/uuid edit-block) (string/blank? (state/get-edit-content)) (not pdf-area?))
insert-opts' (if insert-to-current-block-page?
@@ -1486,6 +1465,8 @@
(or new-entity
(throw (ex-info "Can't save asset" {:files files}))))))))))
(def insert-command! editor-common-handler/insert-command!)
(defn db-upload-assets!
"Paste asset for db graph and insert link to current editing block"
[repo id ^js files format uploading? drop-or-paste?]

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
(ns frontend.handler.file-based.editor
"File-based graph implementation"
(:require [clojure.string :as string]
[electron.ipc :as ipc]
[frontend.commands :as commands]
[frontend.config :as config]
[frontend.date :as date]
@@ -9,8 +10,6 @@
[frontend.db.query-dsl :as query-dsl]
[frontend.format.block :as block]
[frontend.format.mldoc :as mldoc]
[frontend.fs :as fs]
[frontend.fs.capacitor-fs :as capacitor-fs]
[frontend.handler.assets :as assets-handler]
[frontend.handler.block :as block-handler]
[frontend.handler.common.editor :as editor-common-handler]
@@ -19,14 +18,12 @@
[frontend.handler.file-based.repeated :as repeated]
[frontend.handler.file-based.status :as status]
[frontend.handler.property.file :as property-file]
[frontend.mobile.util :as mobile-util]
[frontend.modules.outliner.op :as outliner-op]
[frontend.modules.outliner.ui :as ui-outliner-tx]
[frontend.state :as state]
[frontend.util :as util]
[frontend.util.file-based.clock :as clock]
[frontend.util.file-based.drawer :as drawer]
[goog.crypt.base64 :as base64]
[logseq.common.path :as path]
[logseq.common.util :as common-util]
[logseq.common.util.block-ref :as block-ref]
@@ -302,7 +299,7 @@
(p/all
(for [[index ^js file] (map-indexed vector files)]
;; WARN file name maybe fully qualified path when paste file
(p/let [file-name (util/node-path.basename (.-name file))
(let [file-name (util/node-path.basename (.-name file))
[file-stem ext-full ext-base] (if file-name
(let [ext-base (util/node-path.extname file-name)
ext-full (if-not (config/extname-of-supported? ext-base)
@@ -317,36 +314,13 @@
(not (nil? matched-alias))
(string/replace #"^[.\/\\]*assets[\/\\]+" ""))
dir (or (:dir matched-alias) repo-dir)]
(if (util/electron?)
(do (js/console.debug "Debug: Copy Asset #" dir file-rpath)
(-> (if-let [from (not-empty (.-path file))]
(js/window.apis.copyFileToAssets dir file-rpath from)
(p/let [content (.arrayBuffer file)]
(fs/write-file! repo repo-dir file-rpath content {:skip-compare? true})))
(p/then
(fn [dest]
[file-rpath
(if (string? dest) (js/File. #js[] dest) file)
(path/path-join dir file-rpath)
matched-alias]))
(p/catch #(js/console.error "Debug: Copy Asset Error#" %))))
(->
(p/do! (js/console.debug "Debug: Writing Asset #" dir file-rpath)
(cond
(mobile-util/native-platform?)
;; capacitor fs accepts Blob, File implements Blob
(p/let [buffer (.arrayBuffer file)
content (base64/encodeByteArray (js/Uint8Array. buffer))
fpath (path/path-join dir file-rpath)]
(capacitor-fs/<write-file-with-base64 fpath content))
:else ; nfs
(fs/write-file! repo dir file-rpath (.stream file) nil))
[file-rpath file (path/path-join dir file-rpath) matched-alias])
(p/catch (fn [error]
(prn :paste-file-error)
(js/console.error error))))))))))
(p/let [content (.arrayBuffer file)
file-fpath (path/path-join dir file-rpath)]
;; file based version support electron only
(ipc/ipc "writeFile" repo file-fpath content))
[file-rpath file (path/path-join dir file-rpath) matched-alias]))))))
;; assets/journals_2021_02_03_1612350230540_0.png
(defn resolve-relative-path

View File

@@ -289,7 +289,7 @@
(let [dir (config/get-repo-dir repo)]
(p/let [content (fs/read-file dir file)]
(let [new-content (string/replace content (str id) (str (random-uuid)))]
(p/let [_ (fs/write-file! repo
(p/let [_ (fs/write-plain-text-file! repo
dir
file
new-content

View File

@@ -1,28 +1,28 @@
(ns frontend.handler.file-based.file
"Provides util handler fns for file graph files"
(:refer-clojure :exclude [load-file])
(:require [frontend.config :as config]
(:require [electron.ipc :as ipc]
[frontend.config :as config]
[frontend.db :as db]
[frontend.db.file-based.model :as file-model]
[frontend.fs :as fs]
[frontend.fs.nfs :as nfs]
[frontend.fs.capacitor-fs :as capacitor-fs]
[frontend.handler.file-based.reset-file :as reset-file-handler]
[frontend.fs.nfs :as nfs]
[frontend.handler.common.config-edn :as config-edn-common-handler]
[frontend.handler.repo-config :as repo-config-handler]
[frontend.handler.file-based.reset-file :as reset-file-handler]
[frontend.handler.global-config :as global-config-handler]
[frontend.handler.repo-config :as repo-config-handler]
[frontend.handler.ui :as ui-handler]
[frontend.mobile.util :as mobile-util]
[frontend.schema.handler.global-config :as global-config-schema]
[frontend.schema.handler.repo-config :as repo-config-schema]
[frontend.state :as state]
[frontend.util :as util]
[logseq.common.util :as common-util]
[electron.ipc :as ipc]
[lambdaisland.glogi :as log]
[promesa.core :as p]
[frontend.mobile.util :as mobile-util]
[logseq.common.config :as common-config]
[logseq.common.path :as path]
[logseq.common.config :as common-config]))
[logseq.common.util :as common-util]
[promesa.core :as p]))
;; TODO: extract all git ops using a channel
@@ -115,7 +115,7 @@
path-dir (config/get-repo-dir repo)
write-file-options' (merge write-file-options
(when original-content {:old-content original-content}))]
(fs/write-file! repo path-dir path content write-file-options')))
(fs/write-plain-text-file! repo path-dir path content write-file-options')))
(defn alter-global-file
"Does pre-checks on a global file, writes if it's not already written
@@ -127,7 +127,7 @@
(detect-deprecations path content)
(when (validate-file path content)
(-> (p/let [_ (when-not from-disk?
(fs/write-file! "" nil path content {:skip-compare? true}))]
(fs/write-plain-text-file! "" nil path content {:skip-compare? true}))]
(p/do! (global-config-handler/restore-global-config!)
(state/pub-event! [:shortcut/refresh])))
(p/catch (fn [error]
@@ -212,7 +212,7 @@
(-> (p/let [_ (or
(util/electron?)
(nfs/check-directory-permission! repo))]
(fs/write-file! repo (config/get-repo-dir repo) path content
(fs/write-plain-text-file! repo (config/get-repo-dir repo) path content
{:old-content original-content}))
(p/catch (fn [error]
(state/pub-event! [:notification/show

View File

@@ -2,14 +2,14 @@
"This ns is a system component that encapsulates global config functionality.
Unlike repo config, this also manages a directory for configuration. This
component depends on a repo."
(:require [frontend.fs :as fs]
[frontend.state :as state]
[promesa.core :as p]
[shadow.resource :as rc]
(:require [borkdude.rewrite-edn :as rewrite]
[clojure.edn :as edn]
[electron.ipc :as ipc]
[borkdude.rewrite-edn :as rewrite]
[logseq.common.path :as path]))
[frontend.fs :as fs]
[frontend.state :as state]
[logseq.common.path :as path]
[promesa.core :as p]
[shadow.resource :as rc]))
;; Use defonce to avoid broken state on dev reload
;; Also known as home directory a.k.a. '~'
@@ -73,7 +73,7 @@
(rewrite/dissoc result (first ks))
(rewrite/assoc-in result ks v))
new-str-content (str new-result)]
(fs/write-file! nil nil (global-config-path) new-str-content {:skip-compare? true})
(fs/write-plain-text-file! nil nil (global-config-path) new-str-content {:skip-compare? true})
(state/set-global-config! (rewrite/sexpr new-result) new-str-content)))
(defn start

View File

@@ -67,6 +67,13 @@
(invoke-exported-api :unlink_installed_web_plugin key)
(invoke-exported-api :unlink_plugin_user_settings key))
(defn assets-theme-to-file
[theme]
(when theme
(cond-> theme
(util/electron?)
(update :url #(some-> % (string/replace-first "assets://" "file://"))))))
(defn load-plugin-preferences
[]
(-> (invoke-exported-api :load_user_preferences)
@@ -211,7 +218,6 @@
(let [e (or evt ctx)]
(when-let [{:keys [status payload only-check]} (bean/->clj e)]
(case (keyword status)
:completed
(let [{:keys [id dst name title theme web-pkg]} payload
name (or title name "Untitled")]
@@ -333,6 +339,7 @@
:action (fn []
(state/pub-event!
[:exec-plugin-cmd {:type type :key key :pid pid :cmd cmd :action action}]))}]
palette-cmd))
(defn simple-cmd-keybinding->shortcut-args
@@ -483,7 +490,7 @@
(defn select-a-plugin-theme
[pid]
(when-let [themes (get (group-by :pid (:plugin/installed-themes @state/state)) pid)]
(when-let [theme (first themes)]
(when-let [theme (assets-theme-to-file (first themes))]
(js/LSPluginCore.selectTheme (bean/->js theme)))))
(defn update-plugin-settings-state
@@ -642,7 +649,7 @@
dotroot (get-ls-dotdir-root)
filepath (util/node-path.join dotroot dirname (str key ".json"))]
(if (util/electron?)
(fs/write-file! repo nil filepath (js/JSON.stringify data nil 2) {:skip-compare? true})
(fs/write-plain-text-file! repo nil filepath (js/JSON.stringify data nil 2) {:skip-compare? true})
(idb/set-item! filepath data))))))
(defn make-fn-to-unlink-dotdir-json
@@ -882,9 +889,16 @@
(clear-commands! pid)
(unregister-plugin-themes pid)))
(.on "themes-changed" (fn [^js themes]
(swap! state/state assoc :plugin/installed-themes
(vec (mapcat (fn [[pid vs]] (mapv #(assoc % :pid pid) (bean/->clj vs))) (bean/->clj themes))))))
(.on "theme-selected" (fn [^js theme]
(let [theme (bean/->clj theme)
theme (assets-theme-to-file theme)
url (:url theme)
mode (:mode theme)]
(when mode
(state/set-custom-theme! mode theme)
(state/set-theme-mode! mode))
(state/set-state! :plugin/selected-theme url)
(hook-plugin-app :theme-changed theme))))
(.on "theme-selected" (fn [^js theme ^js opts]
(let [theme (bean/->clj theme)

View File

@@ -40,14 +40,14 @@ when a plugin is installed, updated or removed"
str)]
;; fs protocols require repo and dir when they aren't necessary. For this component,
;; neither is needed so these are blank and nil respectively
(fs/write-file! "" nil (plugin-config-path) updated-content {:skip-compare? true})))
(fs/write-plain-text-file! "" nil (plugin-config-path) updated-content {:skip-compare? true})))
(defn remove-plugin
"Removes a plugin from plugin.edn"
[plugin-id]
(p/let [content (fs/read-file "" (plugin-config-path))
updated-content (-> content rewrite/parse-string (rewrite/dissoc (keyword plugin-id)) str)]
(fs/write-file! "" nil (plugin-config-path) updated-content {:skip-compare? true})))
(fs/write-plain-text-file! "" nil (plugin-config-path) updated-content {:skip-compare? true})))
(defn- create-plugin-config-file-if-not-exists
[]

View File

@@ -1,14 +1,13 @@
(ns frontend.util.persist-var
"System-component-like ns that provides an atom-like abstraction over an edn
file"
(:require [frontend.config :as config]
[frontend.state :as state]
(:require [cljs.reader :as reader]
[frontend.config :as config]
[frontend.fs :as fs]
[frontend.state :as state]
[frontend.util :as util]
[cljs.reader :as reader]
[promesa.core :as p]))
(defn- load-rpath
"Returns the relative path to the file that stores the persist-var"
[location]
@@ -67,7 +66,7 @@
repo (state/get-current-repo)
content (str (get-in @*value [repo :value]))
dir (config/get-repo-dir repo)]
(fs/write-file! repo dir path content {:skip-compare? true}))))
(fs/write-plain-text-file! repo dir path content {:skip-compare? true}))))
IDeref
(-deref [_this]
@@ -83,7 +82,6 @@
(-pr-writer [_ w _opts]
(write-all w (str "#PersistVar[" @*value ", loc: " location "]"))))
(def *all-persist-vars (atom []))
(defn load-vars []
@@ -106,6 +104,4 @@
(comment
(do
(def bbb (persist-var 1 "aaa"))
(-save bbb)
))
(-save bbb)))

View File

@@ -9,8 +9,8 @@
[frontend.db :as db]
[frontend.db.async :as db-async]
[frontend.db.conn :as conn]
[frontend.db.model :as db-model]
[frontend.db.file-based.model :as file-model]
[frontend.db.model :as db-model]
[frontend.db.query-custom :as query-custom]
[frontend.db.query-dsl :as query-dsl]
[frontend.db.query-react :as query-react]
@@ -223,7 +223,7 @@
(fn [path ^js data]
(let [repo ""
path (util/node-path.join path "package.json")]
(fs/write-file! repo nil path (js/JSON.stringify data nil 2) {:skip-compare? true}))))
(fs/write-plain-text-file! repo nil path (js/JSON.stringify data nil 2) {:skip-compare? true}))))
(def ^:export save_focused_code_editor_content
(fn []
@@ -243,7 +243,7 @@
user-path-root (util/node-path.dirname user-path)
exist? (fs/file-exists? user-path-root "")
_ (when-not exist? (fs/mkdir-recur! user-path-root))
_ (fs/write-file! repo nil user-path content {:skip-compare? true})]
_ (fs/write-plain-text-file! repo nil user-path content {:skip-compare? true})]
user-path))
(defn ^:export write_dotdir_file
@@ -379,7 +379,7 @@
path (plugin-handler/get-ls-dotdir-root)
path (util/node-path.join path "preferences.json")]
(if (util/electron?)
(fs/write-file! repo nil path (js/JSON.stringify data nil 2) {:skip-compare? true})
(fs/write-plain-text-file! repo nil path (js/JSON.stringify data nil 2) {:skip-compare? true})
(idb/set-item! path data))))))
(def ^:export load_plugin_user_settings
@@ -666,7 +666,6 @@
:journal? journal
:create-first-block? (if (boolean? createFirstBlock) createFirstBlock true)
:format format}
(not db-base?)
(assoc :properties properties))))
_ (when (and db-base? (seq properties))

View File

@@ -1,10 +1,10 @@
(ns logseq.sdk.git
(:require [cljs-bean.core :as bean]
[promesa.core :as p]
[frontend.state :as state]
[frontend.handler.shell :as shell]
[frontend.config :as config]
[frontend.fs :as fs]))
[frontend.fs :as fs]
[frontend.handler.shell :as shell]
[frontend.state :as state]
[promesa.core :as p]))
(defn ^:export exec_command
[^js args]
@@ -25,4 +25,4 @@
(when-let [repo (and (string? content) (state/get-current-repo))]
(p/let [file ".gitignore"
dir (config/get-repo-dir repo)
_ (fs/write-file! repo dir file content {:skip-compare? true})])))
_ (fs/write-plain-text-file! repo dir file content {:skip-compare? true})])))

File diff suppressed because it is too large Load Diff

2570
yarn.lock

File diff suppressed because it is too large Load Diff