diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 497410b8d..b12ff7d33 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -78,7 +78,8 @@ [rum.core :as rum] [shadow.loader :as loader] [datascript.impl.entity :as e] - [logseq.common.path :as path])) + [logseq.common.path :as path] + [frontend.handler.page :as page-handler])) @@ -2629,6 +2630,7 @@ (editor-handler/unhighlight-blocks!))) (defn- block-drop + "Block on-drop handler" [^js event uuid target-block *move-to] (util/stop event) (when-not (dnd-same-block? uuid) @@ -2637,15 +2639,53 @@ selected (db/pull-many (state/get-current-repo) '[*] lookup-refs) blocks (if (seq selected) selected [@*dragging-block]) blocks (remove-nils blocks)] - (if-not (seq blocks) - (when-let [text (.getData (.-dataTransfer event) "text/plain")] - (editor-handler/api-insert-new-block! - text - {:block-uuid uuid - :edit-block? false - :sibling? (= @*move-to :sibling) - :before? (= @*move-to :top)})) - (dnd/move-blocks event blocks target-block @*move-to)))) + (if (seq blocks) + ;; dnd block moving in current Logseq instance + (dnd/move-blocks event blocks target-block @*move-to) + ;; handle DataTransfer + (let [repo (state/get-current-repo) + data-transfer (.-dataTransfer event) + transfer-types (js->clj (.-types data-transfer)) + transfer-type (first transfer-types)] + (cond + (contains? transfer-types "text/plain") + (let [text (.getData data-transfer "text/plain")] + (editor-handler/api-insert-new-block! + text + {:block-uuid uuid + :edit-block? false + :sibling? (= @*move-to :sibling) + :before? (= @*move-to :top)})) + + (= transfer-type "Files") + (let [files (.-files data-transfer) + format (:block/format target-block)] + (when (config/local-db? repo) + ;; Basically the same logic as editor-handler/upload-asset, + ;; does not require edting + (-> (editor-handler/save-assets! repo (js->clj files)) + (p/then + (fn [res] + (when-let [[asset-file-name file-obj asset-file-fpath matched-alias] (and (seq res) (first res))] + (let [image? (config/ext-of-image? asset-file-name) + link-content (assets-handler/get-asset-file-link format + (if matched-alias + (str + (if image? "../assets/" "") + "@" (:name matched-alias) "/" asset-file-name) + (editor-handler/resolve-relative-path (or asset-file-fpath asset-file-name))) + (if file-obj (.-name file-obj) (if image? "image" "asset")) + image?)] + (editor-handler/api-insert-new-block! + link-content + {:block-uuid uuid + :edit-block? false + :sibling? (= @*move-to :sibling) + :before? (= @*move-to :top)})))))))) + + :else + (prn ::unhandled-drop-data-transfer-type transfer-types))) + ))) (block-drag-end event *move-to)) (defn- block-mouse-over diff --git a/src/main/frontend/extensions/tldraw.cljs b/src/main/frontend/extensions/tldraw.cljs index a77617e9d..21509286b 100644 --- a/src/main/frontend/extensions/tldraw.cljs +++ b/src/main/frontend/extensions/tldraw.cljs @@ -66,7 +66,7 @@ (defn save-asset-handler [file] - (-> (editor-handler/save-assets! nil (state/get-current-repo) [(js->clj file)]) + (-> (editor-handler/save-assets! (state/get-current-repo) [(js->clj file)]) (p/then (fn [res] (when-let [[asset-file-name _ full-file-path] (and (seq res) (first res))] diff --git a/src/main/frontend/handler/assets.cljs b/src/main/frontend/handler/assets.cljs index d22a2bff5..5f4ad2d7a 100644 --- a/src/main/frontend/handler/assets.cljs +++ b/src/main/frontend/handler/assets.cljs @@ -113,6 +113,19 @@ (get-alias-dirs))] alias))) +(defn get-asset-file-link + "Link text for inserting to markdown/org" + [format url file-name image?] + (let [pdf? (and url (string/ends-with? (string/lower-case url) ".pdf")) + media? (and url (or (config/ext-of-audio? url) + (config/ext-of-video? url)))] + (case (keyword format) + :markdown (util/format (str (when (or image? media? pdf?) "!") "[%s](%s)") file-name url) + :org (if image? + (util/format "[[%s]]" url) + (util/format "[[%s][%s]]" url file-name)) + nil))) + (comment (normalize-asset-resource-url "https://x.com/a.pdf") (normalize-asset-resource-url "./a/b.pdf") diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 8985cdd3f..e2743879c 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -46,6 +46,7 @@ [goog.dom :as gdom] [goog.dom.classes :as gdom-classes] [goog.object :as gobj] + [goog.crypt.base64 :as base64] [lambdaisland.glogi :as log] [logseq.db.schema :as db-schema] [logseq.graph-parser.block :as gp-block] @@ -57,7 +58,8 @@ [logseq.graph-parser.util.block-ref :as block-ref] [logseq.graph-parser.util.page-ref :as page-ref] [promesa.core :as p] - [rum.core :as rum])) + [rum.core :as rum] + [frontend.fs.capacitor-fs :as capacitor-fs])) ;; FIXME: should support multiple images concurrently uploading @@ -1375,19 +1377,6 @@ (when restore? (commands/restore-state))) -(defn get-asset-file-link - "Link text for inserting to markdown/org" - [format url file-name image?] - (let [pdf? (and url (string/ends-with? (string/lower-case url) ".pdf")) - media? (and url (or (config/ext-of-audio? url) - (config/ext-of-video? url)))] - (case (keyword format) - :markdown (util/format (str (when (or image? media? pdf?) "!") "[%s](%s)") file-name url) - :org (if image? - (util/format "[[%s]]" url) - (util/format "[[%s][%s]]" url file-name)) - nil))) - (defn- ensure-assets-dir! [repo] (p/let [repo-dir (config/get-repo-dir repo) @@ -1405,7 +1394,7 @@ "Save incoming(pasted) assets to assets directory. Returns: [file-rpath file-obj file-fpath matched-alias]" - ([_ repo files] + ([repo files] (p/let [[repo-dir assets-dir] (ensure-assets-dir! repo)] (save-assets! repo repo-dir assets-dir files (fn [index file-stem] @@ -1449,7 +1438,13 @@ (p/catch #(js/console.error "Debug: Copy Asset Error#" %)))) (p/do! (js/console.debug "Debug: Writing Asset #" dir file-rpath) - (fs/write-file! repo dir file-rpath (.stream file) nil) + (if (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/ (save-assets! block repo (js->clj files)) + (-> (save-assets! repo (js->clj files)) ;; FIXME: only the first asset is handled (p/then (fn [res] @@ -1542,7 +1537,7 @@ (let [image? (config/ext-of-image? asset-file-name)] (insert-command! id - (get-asset-file-link format + (assets-handler/get-asset-file-link format (if matched-alias (str (if image? "../assets/" "") diff --git a/src/main/frontend/mobile/camera.cljs b/src/main/frontend/mobile/camera.cljs index 9a270e2bd..346e07b52 100644 --- a/src/main/frontend/mobile/camera.cljs +++ b/src/main/frontend/mobile/camera.cljs @@ -1,14 +1,15 @@ (ns frontend.mobile.camera (:require ["@capacitor/camera" :refer [Camera CameraResultType]] ["@capacitor/filesystem" :refer [Filesystem]] - [lambdaisland.glogi :as log] - [promesa.core :as p] + [frontend.commands :as commands] + [frontend.date :as date] + [frontend.handler.assets :as assets-handler] [frontend.handler.editor :as editor-handler] [frontend.state :as state] - [frontend.date :as date] - [frontend.commands :as commands] + [frontend.util.cursor :as cursor] [goog.object :as gobj] - [frontend.util.cursor :as cursor])) + [lambdaisland.glogi :as log] + [promesa.core :as p])) (defn- take-or-choose-photo [] (-> (.getPhoto Camera (clj->js @@ -55,6 +56,6 @@ (commands/simple-insert! id (str left-padding - (editor-handler/get-asset-file-link format (str "../assets/" filename) filename true) + (assets-handler/get-asset-file-link format (str "../assets/" filename) filename true) " ") {}))))) diff --git a/src/main/frontend/mobile/intent.cljs b/src/main/frontend/mobile/intent.cljs index 74c3366ce..402fcee54 100644 --- a/src/main/frontend/mobile/intent.cljs +++ b/src/main/frontend/mobile/intent.cljs @@ -8,6 +8,7 @@ [frontend.config :as config] [frontend.date :as date] [frontend.db :as db] + [frontend.handler.assets :as assets-handler] [frontend.handler.editor :as editor-handler] [frontend.handler.notification :as notification] [frontend.mobile.util :as mobile-util] @@ -72,7 +73,7 @@ (fn [error] (log/error :copy-file-error {:error error}))) url (util/format "../assets/%s" basename) - url (editor-handler/get-asset-file-link format url label true) + url (assets-handler/get-asset-file-link format url label true) template (get-in (state/get-config) [:quick-capture-templates :media] "**{time}** [[quick capture]]: {url}")] @@ -169,7 +170,7 @@ (fn [error] (log/error :copy-file-error {:error error}))) url (util/format "../assets/%s" basename) - url-link (editor-handler/get-asset-file-link format url label true)] + url-link (assets-handler/get-asset-file-link format url label true)] url-link)) (defn- handle-payload-resource diff --git a/src/main/frontend/mobile/record.cljs b/src/main/frontend/mobile/record.cljs index caf971764..e789b9d02 100644 --- a/src/main/frontend/mobile/record.cljs +++ b/src/main/frontend/mobile/record.cljs @@ -1,14 +1,15 @@ (ns frontend.mobile.record (:require ["@capacitor/filesystem" :refer [Filesystem]] ["capacitor-voice-recorder" :refer [VoiceRecorder]] - [promesa.core :as p] + [clojure.string :as string] + [frontend.date :as date] + [frontend.db :as db] + [frontend.handler.assets :as assets-handler] [frontend.handler.editor :as editor-handler] [frontend.state :as state] - [frontend.date :as date] - [lambdaisland.glogi :as log] [frontend.util :as util] - [clojure.string :as string] - [frontend.db :as db])) + [lambdaisland.glogi :as log] + [promesa.core :as p])) (defn request-audio-recording-permission [] (p/then @@ -56,7 +57,7 @@ (log/error :file/write-failed {:path path :error error}))) url (util/format "../assets/%s" filename) - file-link (editor-handler/get-asset-file-link format url filename true) + file-link (assets-handler/get-asset-file-link format url filename true) args (merge (if (parse-uuid page) {:block-uuid (uuid page)} {:page page})