Merge pull request #3374 from logseq/enhance/mobile

Support photo upload/undo on mobile
pull/3499/head
Tienson Qin 2021-12-16 17:24:31 +08:00 committed by GitHub
commit 2a081a7902
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 183 additions and 87 deletions

View File

@ -12,6 +12,7 @@ dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-filesystem')
implementation project(':capacitor-splash-screen')
implementation project(':capacitor-camera')
}

View File

@ -10,5 +10,9 @@
{
"pkg": "@capacitor/splash-screen",
"classpath": "com.capacitorjs.plugins.splashscreen.SplashScreenPlugin"
},
{
"pkg": "@capacitor/camera",
"classpath": "com.capacitorjs.plugins.camera.CameraPlugin"
}
]

View File

@ -10,3 +10,6 @@ project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacit
include ':capacitor-splash-screen'
project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android')
include ':capacitor-camera'
project(':capacitor-camera').projectDir = new File('../node_modules/@capacitor/camera/android')

View File

@ -16,6 +16,7 @@
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
7435D10C2704659F00AB88E0 /* FolderPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7435D10B2704659F00AB88E0 /* FolderPicker.swift */; };
7435D10F2704660B00AB88E0 /* FolderPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7435D10E2704660B00AB88E0 /* FolderPicker.m */; };
C3718FCEFAECFFB66E93FFC4 /* Pods_Logseq.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */; };
D32752BE275496C60039291C /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D32752BD275496C60039291C /* CloudKit.framework */; };
D3D62A0A275C92880003FBDC /* FileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A09275C92880003FBDC /* FileContainer.swift */; };
D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A0B275C928F0003FBDC /* FileContainer.m */; };
@ -35,6 +36,7 @@
7435D10D2704660A00AB88E0 /* App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "App-Bridging-Header.h"; sourceTree = "<group>"; };
7435D10E2704660B00AB88E0 /* FolderPicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FolderPicker.m; sourceTree = "<group>"; };
8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Logseq.release.xcconfig"; path = "Target Support Files/Pods-Logseq/Pods-Logseq.release.xcconfig"; sourceTree = "<group>"; };
B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Logseq.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D32752BC275496A60039291C /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
D32752BD275496C60039291C /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
D32752BF2754C5AB0039291C /* AppDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppDebug.entitlements; sourceTree = "<group>"; };
@ -49,6 +51,7 @@
buildActionMask = 2147483647;
files = (
D32752BE275496C60039291C /* CloudKit.framework in Frameworks */,
C3718FCEFAECFFB66E93FFC4 /* Pods_Logseq.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -99,6 +102,7 @@
isa = PBXGroup;
children = (
D32752BD275496C60039291C /* CloudKit.framework */,
B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */,
);
name = Frameworks;
sourceTree = "<group>";

View File

@ -2,88 +2,94 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>APFiles</key>
<dict>
<key>APFileDescriptionKey</key>
<string></string>
<key>APFileDestinationPath</key>
<string></string>
<key>APFileName</key>
<string></string>
<key>APFileSourcePath</key>
<string></string>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Logseq</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSDocumentsFolderUsageDescription</key>
<string></string>
<key>NSDownloadsFolderUsageDescription</key>
<string></string>
<key>NSFileProviderDomainUsageDescription</key>
<string></string>
<key>NSFileProviderPresenceUsageDescription</key>
<string></string>
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.com.logseq.logseq</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerName</key>
<string>Logseq</string>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>ANY</string>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportsDocumentBrowser</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>APFiles</key>
<dict>
<key>APFileDescriptionKey</key>
<string></string>
<key>APFileDestinationPath</key>
<string></string>
<key>APFileName</key>
<string></string>
<key>APFileSourcePath</key>
<string></string>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Logseq</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSDocumentsFolderUsageDescription</key>
<string></string>
<key>NSDownloadsFolderUsageDescription</key>
<string></string>
<key>NSFileProviderDomainUsageDescription</key>
<string></string>
<key>NSFileProviderPresenceUsageDescription</key>
<string></string>
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.com.logseq.logseq</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerName</key>
<string>Logseq</string>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>ANY</string>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string></string>
<key>NSCameraUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string></string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportsDocumentBrowser</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
</dict>
</plist>

View File

@ -12,6 +12,7 @@ def capacitor_pods
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem'
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera'
end
target 'Logseq' do

View File

@ -69,7 +69,8 @@
"@capacitor/filesystem": "1.0.6",
"@capacitor/ios": "3.2.2",
"@capacitor/splash-screen": "1.1.3",
"@excalidraw/excalidraw": "0.4.3",
"@capacitor/camera": "1.2.1",
"@excalidraw/excalidraw": "0.4.2",
"@kanru/rage-wasm": "0.2.1",
"@sentry/browser": "6.4.1",
"@sentry/electron": "2.5.1",

View File

@ -7,6 +7,7 @@
[frontend.components.datetime :as datetime-comp]
[frontend.components.search :as search]
[frontend.components.svg :as svg]
[frontend.mobile.camera :as mobile-camera]
[frontend.config :as config]
[frontend.handler.notification :as notification]
[frontend.db :as db]
@ -23,7 +24,8 @@
[frontend.util.keycode :as keycode]
[goog.dom :as gdom]
[promesa.core :as p]
[rum.core :as rum]))
[rum.core :as rum]
[frontend.handler.history :as history]))
(rum/defc commands < rum/reactive
[id format]
@ -228,7 +230,14 @@
(:offset-top vw-state))
0)}
:class (util/classnames [{:is-vw-pending (boolean vw-pending?)}])}
[:div.flex.justify-around.w-full
[:div.flex {:style {:overflow "overlay"}}
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
(util/stop e)
(mobile-camera/embed-photo parent-id))}
(ui/icon "camera"
{:style {:fontSize ui/icon-size}})]]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
@ -268,6 +277,13 @@
(.focus input)))}
(ui/icon "arrow-back"
{:style {:fontSize ui/icon-size}})]]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
(util/stop e)
(history/undo! e))}
(ui/icon "rotate"
{:style {:fontSize ui/icon-size}})]]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]

View File

@ -1594,10 +1594,14 @@
(util/electron?)
(str "assets://" repo-dir path)
(mobile/is-native-platform?)
(mobile/native-android?)
(mobile/convert-file-src
(str "file://" repo-dir path))
(mobile/native-ios?)
(mobile/convert-file-src
(str repo-dir path))
:else
(let [handle-path (str "handle" repo-dir path)
cached-url (get @*assets-url-cache (keyword handle-path))]

View File

@ -0,0 +1,52 @@
(ns frontend.mobile.camera
(:require ["@capacitor/camera" :refer [Camera CameraResultType]]
["@capacitor/filesystem" :refer [Filesystem]]
[lambdaisland.glogi :as log]
[promesa.core :as p]
[frontend.handler.editor :as editor-handler]
[frontend.state :as state]
[frontend.date :as date]
[frontend.util :as util]
[frontend.commands :as commands]
[frontend.mobile.util :as mobile-util]))
(defn- save-photo []
(p/let [photo (p/catch
(.getPhoto Camera (clj->js
{:allowEditing (get-in
(state/get-config)
[:mobile/photo :allow-editing?])
:saveToGallery true
:resultType (.-Base64 CameraResultType)}))
(fn [error]
(log/error :photo/get-failed {:error error})))
[repo-dir assets-dir] (editor-handler/ensure-assets-dir! (state/get-current-repo))
filename (str (date/get-date-time-string-2) ".jpeg")
path (cond
(mobile-util/native-android?)
(str "file://" repo-dir "/" assets-dir "/" filename)
(mobile-util/native-ios?)
(str repo-dir assets-dir "/" filename)
:else
(str repo-dir assets-dir "/" filename))
_file (p/catch
(.writeFile Filesystem (clj->js {:data (.-base64String photo)
:path path
:recursive true}))
(fn [error]
(log/error :file/write-failed {:path path
:error error})))]
(p/resolved filename)))
(defn embed-photo [id]
(let [block (state/get-edit-block)
format (:block/format block)]
(p/let [filename (save-photo)]
(commands/simple-insert!
id
(case format
:org (util/format "[[../assets/%s]]" filename)
(util/format "![%s](../assets/%s)" filename filename))
{}))))

View File

@ -182,4 +182,8 @@
;; :enabled-in-all-blocks true ;display logbook in all blocks after timetracking
;; :enabled-in-timestamped-blocks false ;don't display logbook at all
;; }
;; Mobile photo uploading setup
;; :mobile/photo
;; {:allow-editing? true}
}