Merge branch 'master' into feat/integrated-title-bar

pull/9442/head
Konstantinos 2023-05-23 21:06:33 +03:00 committed by GitHub
commit 13d29a072f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 334 additions and 166 deletions

View File

@ -6,8 +6,8 @@ android {
applicationId "com.logseq.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 59
versionName "0.9.6"
versionCode 60
versionName "0.9.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

View File

@ -92,10 +92,23 @@ public class FsWatcher extends Plugin {
shouldRead = true;
}
URI dir = (new File(mPath)).toURI();
URI fpath = f.toURI();
Uri dir = Uri.fromFile(new File(mPath));
Uri fpath = Uri.fromFile(f);
String relpath = null;
obj.put("path", Normalizer.normalize(dir.relativize(fpath).toString(), Normalizer.Form.NFC));
if (fpath.getPath().startsWith(dir.getPath())) {
relpath = fpath.getPath().substring(dir.getPath().length());
if (relpath.startsWith("/")) {
relpath = relpath.substring(1);
}
relpath = Uri.decode(relpath);
} else {
Log.e("FsWatcher", "file path not under watch path");
return;
}
obj.put("path", Normalizer.normalize(relpath, Normalizer.Form.NFC));
obj.put("dir", Uri.fromFile(new File(mPath))); // Uri is for Android. URI is for RFC compatible
JSObject stat;

View File

@ -27,6 +27,7 @@
D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A0B275C928F0003FBDC /* FileContainer.m */; };
FE647FF427BDFEDE00F3206B /* FsWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE647FF327BDFEDE00F3206B /* FsWatcher.swift */; };
FE647FF627BDFEF500F3206B /* FsWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = FE647FF527BDFEF500F3206B /* FsWatcher.m */; };
FE96D6102A1B811A001ECE32 /* SharedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE96D60F2A1B811A001ECE32 /* SharedData.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -83,6 +84,7 @@
DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Logseq.debug.xcconfig"; path = "Target Support Files/Pods-Logseq/Pods-Logseq.debug.xcconfig"; sourceTree = "<group>"; };
FE647FF327BDFEDE00F3206B /* FsWatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FsWatcher.swift; sourceTree = "<group>"; };
FE647FF527BDFEF500F3206B /* FsWatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FsWatcher.m; sourceTree = "<group>"; };
FE96D60F2A1B811A001ECE32 /* SharedData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedData.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -156,6 +158,7 @@
children = (
5FFF7D7927E4E70700B00DA8 /* ShareViewController.entitlements */,
5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */,
FE96D60F2A1B811A001ECE32 /* SharedData.swift */,
5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */,
5FFF7D7127E343FA00B00DA8 /* Info.plist */,
);
@ -345,6 +348,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FE96D6102A1B811A001ECE32 /* SharedData.swift in Sources */,
5FFF7D6D27E343FA00B00DA8 /* ShareViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -438,7 +442,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -492,7 +496,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
@ -515,7 +519,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.9.6;
MARKETING_VERSION = 0.9.7;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -542,7 +546,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.9.6;
MARKETING_VERSION = 0.9.7;
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
@ -565,9 +569,9 @@
INFOPLIST_FILE = ShareViewController/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareViewController;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 0.9.6;
MARKETING_VERSION = 0.9.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
@ -592,9 +596,9 @@
INFOPLIST_FILE = ShareViewController/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareViewController;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 0.9.6;
MARKETING_VERSION = 0.9.7;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -8,6 +8,8 @@
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationDictionaryVersion</key>
<integer>2</integer>
<key>NSExtensionActivationSupportsFileWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
@ -17,9 +19,9 @@
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
<integer>1</integer>
<integer>3</integer>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
<integer>3</integer>
<key>NSExtensionActivationUsesStrictMatching</key>
<false/>
</dict>

View File

@ -9,182 +9,180 @@
import MobileCoreServices
import Social
import UIKit
class ShareItem {
public var title: String?
public var type: String?
public var url: String?
}
import UniformTypeIdentifiers
class ShareViewController: UIViewController {
private var shareItems: [ShareItem] = []
private var sharedData: SharedData = SharedData.init(resources: [])
var groupContainerUrl: URL? {
return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.logseq.logseq")
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
super.viewDidAppear(animated)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
private func sendData() {
let queryItems = shareItems.map {
let encoder: JSONEncoder = JSONEncoder()
let data = try? encoder.encode(self.sharedData)
let queryPayload = String(decoding: data!, as: UTF8.self)
let queryItems =
[
URLQueryItem(
name: "title",
value: $0.title?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
URLQueryItem(name: "description", value: ""),
URLQueryItem(
name: "type",
value: $0.type?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
URLQueryItem(
name: "url",
value: $0.url?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
name: "payload",
value: queryPayload.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
]
}.flatMap({ $0 })
var urlComps = URLComponents(string: "logseq://shared?")!
urlComps.queryItems = queryItems
openURL(urlComps.url!)
}
fileprivate func createSharedFileUrl(_ url: URL?) -> String {
let copyFileUrl = groupContainerUrl!.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! + "/" + url!
fileprivate func createSharedFileUrl(_ url: URL?) -> URL? {
let tempFilename = url!
.lastPathComponent.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
try? Data(contentsOf: url!).write(to: URL(string: copyFileUrl)!)
let copyFileUrl = groupContainerUrl!.appendingPathComponent(tempFilename)
try? Data(contentsOf: url!).write(to: copyFileUrl)
return copyFileUrl
}
func saveScreenshot(_ image: UIImage) -> String {
// Screenshots, shared images from some system App are passed as UIImage
func saveUIImage(_ image: UIImage) -> URL? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd-HH-mm-ss"
let copyFileUrl = groupContainerUrl!.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
+ dateFormatter.string(from: Date()) + ".png"
let filename = dateFormatter.string(from: Date()) + ".png"
let copyFileUrl = groupContainerUrl!.appendingPathComponent(filename)
do {
try image.pngData()?.write(to: URL(string: copyFileUrl)!)
try image.pngData()?.write(to: copyFileUrl)
return copyFileUrl
} catch {
print(error.localizedDescription)
return ""
return nil
}
}
// Can be a path or a web URL
fileprivate func handleTypeUrl(_ attachment: NSItemProvider)
async throws -> ShareItem
async throws -> SharedResource
{
let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil)
let url = results as! URL?
let shareItem: ShareItem = ShareItem()
var res = SharedResource()
if url!.isFileURL {
shareItem.title = url!.lastPathComponent
shareItem.type = "application/" + url!.pathExtension.lowercased()
shareItem.url = createSharedFileUrl(url)
res.name = url!.lastPathComponent
res.ext = url!.pathExtension
res.type = url!.pathExtensionAsMimeType()
res.url = createSharedFileUrl(url)
} else {
shareItem.title = url!.absoluteString
shareItem.url = url!.absoluteString
shareItem.type = "text/plain"
res.name = url!.absoluteString
res.type = "text/plain"
}
return shareItem
return res
}
fileprivate func handleTypeText(_ attachment: NSItemProvider)
async throws -> ShareItem
async throws -> SharedResource?
{
let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeText as String, options: nil)
let shareItem: ShareItem = ShareItem()
let text = results as! String
shareItem.title = text
shareItem.type = "text/plain"
return shareItem
let item = try await attachment.loadItem(forTypeIdentifier: kUTTypeText as String, options: nil)
self.sharedData.text = item as? String
return nil
}
fileprivate func handleTypeMovie(_ attachment: NSItemProvider)
async throws -> ShareItem
async throws -> SharedResource
{
let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeMovie as String, options: nil)
let shareItem: ShareItem = ShareItem()
let url = results as! URL?
shareItem.title = url!.lastPathComponent
shareItem.type = "video/" + url!.pathExtension.lowercased()
shareItem.url = createSharedFileUrl(url)
return shareItem
let name = url!.lastPathComponent
let ext = url!.pathExtension.lowercased()
let type = url!.pathExtensionAsMimeType()
let sharedUrl = createSharedFileUrl(url)
let res = SharedResource(name: name, ext: ext, type: type, url: sharedUrl)
return res
}
fileprivate func handleTypeImage(_ attachment: NSItemProvider)
async throws -> ShareItem
async throws -> SharedResource
{
let data = try await attachment.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil)
let shareItem: ShareItem = ShareItem()
var res = SharedResource()
switch data {
case let image as UIImage:
shareItem.title = "screenshot"
shareItem.type = "image/png"
shareItem.url = self.saveScreenshot(image)
res.url = self.saveUIImage(image)
res.ext = "png"
res.name = res.url?.lastPathComponent
res.type = res.url?.pathExtensionAsMimeType()
case let url as URL:
shareItem.title = url.lastPathComponent
shareItem.type = "image/" + url.pathExtension.lowercased()
shareItem.url = self.createSharedFileUrl(url)
res.name = url.lastPathComponent
res.ext = url.pathExtension.lowercased()
res.type = url.pathExtensionAsMimeType()
res.url = self.createSharedFileUrl(url)
default:
print("Unexpected image data:", type(of: data))
}
return shareItem
return res
}
override public func viewDidLoad() {
super.viewDidLoad()
shareItems.removeAll()
let extensionItem = extensionContext?.inputItems.first as! NSExtensionItem
sharedData.empty()
let inputItems = extensionContext?.inputItems as! [NSExtensionItem]
Task {
try await withThrowingTaskGroup(
of: ShareItem.self,
of: SharedResource?.self,
body: { taskGroup in
for attachment in extensionItem.attachments! {
if attachment.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
taskGroup.addTask {
return try await self.handleTypeUrl(attachment)
}
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeText as String) {
taskGroup.addTask {
return try await self.handleTypeText(attachment)
}
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeMovie as String) {
taskGroup.addTask {
return try await self.handleTypeMovie(attachment)
}
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
taskGroup.addTask {
return try await self.handleTypeImage(attachment)
for extensionItem in inputItems {
for attachment in extensionItem.attachments! {
if attachment.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
taskGroup.addTask {
return try await self.handleTypeUrl(attachment)
}
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeText as String) {
taskGroup.addTask {
return try await self.handleTypeText(attachment)
}
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeMovie as String) {
taskGroup.addTask {
return try await self.handleTypeMovie(attachment)
}
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
taskGroup.addTask {
return try await self.handleTypeImage(attachment)
}
}
}
}
for try await item in taskGroup {
self.shareItems.append(item)
if let item = item {
self.sharedData.resources.append(item)
}
}
})
self.sendData()
}
}
@discardableResult
@objc func openURL(_ url: URL) -> Bool {
var responder: UIResponder? = self
@ -196,6 +194,14 @@ class ShareViewController: UIViewController {
}
return false
}
}
extension URL {
func pathExtensionAsMimeType() -> String? {
let type = UTType(filenameExtension: self.pathExtension)
return type?.preferredMIMEType
}
}

View File

@ -0,0 +1,25 @@
//
// SharedData.swift
// ShareViewController
//
// Created by Mono Wang on 5/22/23.
//
import Foundation
public struct SharedResource: Decodable, Encodable {
var name: String?
var ext: String?
var type: String?
var url: URL?
}
public struct SharedData: Decodable, Encodable {
var text: String?
var resources: [SharedResource]
mutating func empty() {
text = nil
resources = []
}
}

View File

@ -122,7 +122,7 @@
"path-complete-extname": "1.0.0",
"pixi-graph-fork": "0.2.0",
"pixi.js": "6.2.0",
"posthog-js": "1.10.2",
"posthog-js": "1.57.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-grid-layout": "0.16.6",

View File

@ -1,7 +1,7 @@
{
"name": "Logseq",
"productName": "Logseq",
"version": "0.9.6",
"version": "0.9.7",
"main": "electron.js",
"author": "Logseq",
"license": "AGPL-3.0",

View File

@ -1777,7 +1777,7 @@
(when (sync-state--valid-to-accept-filewatcher-event? sync-state)
(when (or (:mtime stat) (= type "unlink"))
(go
(let [path (path-normalize (remove-dir-prefix dir path))
(let [path (path-normalize path)
files-meta (and (not= "unlink" type)
(<! (<get-local-files-meta
rsapi (:current-syncing-graph-uuid sync-state) dir [path])))

View File

@ -1193,10 +1193,6 @@
(common-handler/copy-to-clipboard-without-id-property! (:block/format block) md-content html sorted-blocks)
(delete-block-aux! block true))))
(defn clear-last-selected-block!
[]
(state/drop-last-selection-block!))
(defn highlight-selection-area!
[end-block]
(when-let [start-block (state/get-selection-start-block-or-first)]
@ -1212,13 +1208,17 @@
(cond
;; when editing, quit editing and select current block
(state/editing?)
(state/exit-editing-and-set-selected-blocks! [(gdom/getElement (state/get-editing-block-dom-id))])
(let [element (gdom/getElement (state/get-editing-block-dom-id))]
(when element
(util/scroll-to-block element)
(state/exit-editing-and-set-selected-blocks! [element])))
;; when selection and one block selected, select next block
(and (state/selection?) (== 1 (count (state/get-selection-blocks))))
(let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed-skip)
element (f (first (state/get-selection-blocks)))]
(when element
(util/scroll-to-block element)
(state/conj-selection-block! element direction)))
;; if same direction, keep conj on same direction
@ -1227,11 +1227,17 @@
first-last (if (= :up direction) first last)
element (f (first-last (state/get-selection-blocks)))]
(when element
(util/scroll-to-block element)
(state/conj-selection-block! element direction)))
;; if different direction, keep clear until one left
(state/selection?)
(clear-last-selected-block!))
(let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed)
last-first (if (= :up direction) last first)
element (f (last-first (state/get-selection-blocks)))]
(when element
(util/scroll-to-block element)
(state/drop-last-selection-block!))))
nil)
(defn on-select-block
@ -2482,13 +2488,6 @@
(.preventDefault e)
(keydown-new-line))))
(defn- scroll-to-block
[block]
(when block
(when-not (util/element-visible? block)
(.scrollIntoView block #js {:behavior "smooth"
:block "center"}))))
(defn- select-first-last
"Select first or last block in viewpoint"
[direction]
@ -2496,7 +2495,7 @@
block (->> (util/get-blocks-noncollapse)
(f))]
(when block
(scroll-to-block block)
(util/scroll-to-block block)
(state/exit-editing-and-set-selected-blocks! [block]))))
(defn- select-up-down [direction]
@ -2509,7 +2508,7 @@
:down util/get-next-block-non-collapsed)
sibling-block (f selected)]
(when (and sibling-block (dom/attr sibling-block "blockid"))
(scroll-to-block sibling-block)
(util/scroll-to-block sibling-block)
(state/exit-editing-and-set-selected-blocks! [sibling-block]))))
(defn- move-cross-boundary-up-down

View File

@ -233,12 +233,20 @@
(state/set-state! :editor/on-paste? true)
(let [clipboard-data (gobj/get e "clipboardData")
html (.getData clipboard-data "text/html")
text (.getData clipboard-data "text")]
text (.getData clipboard-data "text")
has-files? (seq (.-files clipboard-data))]
(cond
(and (string/blank? text) (string/blank? html))
;; When both text and html are blank, paste file if exists.
;; NOTE: util/stop is not called here if no file is provided,
;; so the default paste behavior of the native platform will be used.
(when has-files?
(paste-file-if-exists id e))
;; both file attachment and text/html exist
(and has-files? (state/preferred-pasting-file?))
(paste-file-if-exists id e)
(and (seq (.-files clipboard-data)) (state/preferred-pasting-file?))
(paste-file-if-exists id e)
:else
(let [text' (or (when (gp-util/url? text)
(wrap-macro-url text))

View File

@ -9,7 +9,8 @@
[frontend.handler.route :as route-handler]
[frontend.mobile.intent :as intent]
[frontend.state :as state]
[frontend.util.text :as text-util]))
[frontend.util.text :as text-util]
[logseq.graph-parser.util :as gp-util]))
(def *link-to-another-graph (atom false))
@ -70,8 +71,14 @@
(= hostname "shared")
(let [result (into {} (map (fn [key]
[(keyword key) (.get search-params key)])
["title" "url" "type"]))]
(intent/handle-result result))
["title" "url" "type" "payload"]))]
(if (:payload result)
(let [raw (gp-util/safe-decode-uri-component (:payload result))
payload (-> raw
js/JSON.parse
(js->clj :keywordize-keys true))]
(intent/handle-payload payload))
(intent/handle-result result)))
:else
nil)))

View File

@ -152,7 +152,92 @@
(gp-util/safe-decode-uri-component v)
v))])))
(defn handle-result [result]
(defn- handle-asset-file [url format]
(p/let [basename (node-path/basename url)
label (-> basename util/node-path.name)
path (editor-handler/get-asset-path basename)
_file (p/catch
(.copy Filesystem (clj->js {:from url :to path}))
(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))
(defn- handle-payload-resource
[{:keys [type name ext url] :as resource} format]
(if url
(cond
(contains? (set/union config/doc-formats config/media-formats)
(keyword ext))
(handle-asset-file url format)
:else
(notification/show!
[:div
"Parsing current shared content are not supported. Please report the following codes on "
[:a {:href "https://github.com/logseq/logseq/issues/new?labels=from:in-app&template=bug_report.yaml"
:target "_blank"} "Github"]
". We will look into it soon."
[:pre.code (with-out-str (pprint/pprint resource))]] :warning false))
(cond
(= type "text/plain")
name
:else
(notification/show!
[:div
"Parsing current shared content are not supported. Please report the following codes on "
[:a {:href "https://github.com/logseq/logseq/issues/new?labels=from:in-app&template=bug_report.yaml"
:target "_blank"} "Github"]
". We will look into it soon."
[:pre.code (with-out-str (pprint/pprint resource))]] :warning false))))
(defn handle-payload
"Mobile share intent handler v2, use complex payload to support more types of content."
[payload]
;; use :text template, use {url} as rich text placeholder
(p/let [page (or (state/get-current-page) (string/lower-case (date/journal-name)))
format (db/get-page-format page)
template (get-in (state/get-config)
[:quick-capture-templates :text]
"**{time}** [[quick capture]]: {text} {url}")
{:keys [text resources]} payload
text (or text "")
rich-content (-> (p/all (map (fn [resource]
(handle-payload-resource resource format))
resources))
(p/then (partial string/join "\n")))]
(when (or (not-empty text) (not-empty rich-content))
(let [time (date/get-current-time)
date-ref-name (date/today)
content (-> template
(string/replace "{time}" time)
(string/replace "{date}" date-ref-name)
(string/replace "{text}" text)
(string/replace "{url}" rich-content))
edit-content (state/get-edit-content)
edit-content-blank? (string/blank? edit-content)
edit-content-include-capture? (and (not-empty edit-content)
(string/includes? edit-content "[[quick capture]]"))]
(if (and (state/editing?) (not edit-content-include-capture?))
(if edit-content-blank?
(editor-handler/insert content)
(editor-handler/insert (str "\n" content)))
(do
(editor-handler/escape-editing)
(js/setTimeout #(editor-handler/api-insert-new-block! content {:page page
:edit-block? true
:replace-empty-target? true})
100)))))))
(defn handle-result
"Mobile share intent handler v1, legacy. Only for Android"
[result]
(let [result (decode-received-result result)]
(when-let [type (:type result)]
(cond

View File

@ -405,6 +405,16 @@
%))
(take-while (complement nil?) (iterate #(.-parentElement %) element)))))
#?(:cljs
(defn element-visible?
[element]
(when element
(when-let [r (.getBoundingClientRect element)]
(and (>= (.-top r) 0)
(<= (+ (.-bottom r) 64)
(or (.-innerHeight js/window)
(js/document.documentElement.clientHeight))))))))
#?(:cljs
(defn element-top [elem top]
(when elem
@ -455,6 +465,19 @@
([animate?]
(scroll-to (app-scroll-container-node) 0 animate?))))
#?(:cljs
(defn scroll-to-block
"Scroll into the view to vertically align a non-visible block to the centre
of the visible area"
([block]
(scroll-to-block block true))
([block animate?]
(when block
(when-not (element-visible? block)
(.scrollIntoView block
#js {:behavior (if animate? "smooth" "auto")
:block "center"}))))))
#?(:cljs
(defn link?
[node]
@ -1404,16 +1427,6 @@
(fn [resolve]
(load url resolve)))))
#?(:cljs
(defn element-visible?
[element]
(when element
(when-let [r (.getBoundingClientRect element)]
(and (>= (.-top r) 0)
(<= (+ (.-bottom r) 64)
(or (.-innerHeight js/window)
(js/document.documentElement.clientHeight))))))))
#?(:cljs
(defn copy-image-to-clipboard
[src]

View File

@ -1,3 +1,3 @@
(ns ^:no-doc frontend.version)
(defonce version "0.9.6")
(defonce version "0.9.7")

View File

@ -5807,12 +5807,13 @@ postcss@^8.2.1:
picocolors "^1.0.0"
source-map-js "^1.0.2"
posthog-js@1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.10.2.tgz#74d6c84f9675b65dfd4ff6f4051ed8d3cb974076"
integrity sha512-JNjWstHEexhj5CEKldSeYNyPJbtOvZQ3ZPL55fxU7+f+gTBL8RlOb8eFohCPYIk0VhMf2UM1rXxwVBOeMQQQFw==
posthog-js@1.57.2:
version "1.57.2"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.57.2.tgz#131fb93e2ad099baff4317f3d91a4d6c96a08e7f"
integrity sha512-ER4gkYZasrd2Zwmt/yLeZ5G/nZJ6tpaYBCpx3CvocDx+3F16WdawJlYMT0IyLKHXDniC5+AsjzFd6fi8uyYlJA==
dependencies:
fflate "^0.4.1"
rrweb-snapshot "^1.1.14"
prepend-http@^2.0.0:
version "2.0.0"
@ -6384,6 +6385,11 @@ roarr@^2.15.3:
semver-compare "^1.0.0"
sprintf-js "^1.1.2"
rrweb-snapshot@^1.1.14:
version "1.1.14"
resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-1.1.14.tgz#9d4d9be54a28a893373428ee4393ec7e5bd83fcc"
integrity sha512-eP5pirNjP5+GewQfcOQY4uBiDnpqxNRc65yKPW0eSoU1XamDfc4M8oqpXGMyUyvLyxFDB0q0+DChuxxiU2FXBQ==
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"