Răsfoiți Sursa

Merge branch 'master' into feat/db

Gabriel Horner 2 ani în urmă
părinte
comite
b66bde0230
82 a modificat fișierele cu 876 adăugiri și 780 ștergeri
  1. 1 1
      .github/workflows/build-android.yml
  2. 3 2
      android/app/build.gradle
  3. 3 3
      android/app/capacitor.build.gradle
  4. 7 5
      android/app/src/main/AndroidManifest.xml
  5. 2 2
      android/app/src/main/assets/capacitor.plugins.json
  6. 1 1
      android/app/src/main/java/com/logseq/app/FolderPicker.java
  7. 2 2
      android/build.gradle
  8. 2 2
      android/capacitor.settings.gradle
  9. 1 2
      android/gradle.properties
  10. 1 1
      android/gradle/wrapper/gradle-wrapper.properties
  11. 10 10
      android/variables.gradle
  12. 4 0
      capacitor.config.ts
  13. 1 1
      deps.edn
  14. 1 0
      e2e-tests/accessibility.spec.ts
  15. 1 1
      ios/.gitignore
  16. 4 4
      ios/App/App.xcodeproj/project.pbxproj
  17. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  18. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  19. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  20. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  21. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  22. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  23. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  24. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  25. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  26. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  27. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  28. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  29. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  30. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  31. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  32. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  33. BIN
      ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]
  34. 11 113
      ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json
  35. 1 1
      ios/App/Podfile
  36. 27 19
      package.json
  37. 1 1
      resources/forge.config.js
  38. 11 5
      resources/js/preload.js
  39. 3 2
      resources/package.json
  40. 7 7
      src/electron/electron/configs.cljs
  41. 4 0
      src/electron/electron/core.cljs
  42. 13 2
      src/electron/electron/handler.cljs
  43. 8 2
      src/electron/electron/utils.cljs
  44. 1 1
      src/electron/electron/window.cljs
  45. 1 1
      src/main/frontend/components/block.cljs
  46. 2 2
      src/main/frontend/components/bug_report.cljs
  47. 1 1
      src/main/frontend/components/container.css
  48. 22 18
      src/main/frontend/components/editor.cljs
  49. 6 3
      src/main/frontend/components/header.cljs
  50. 34 12
      src/main/frontend/components/page.cljs
  51. 2 1
      src/main/frontend/components/plugins.cljs
  52. 1 0
      src/main/frontend/components/right_sidebar.cljs
  53. 15 0
      src/main/frontend/components/settings.cljs
  54. 6 1
      src/main/frontend/components/theme.cljs
  55. 1 1
      src/main/frontend/components/whiteboard.css
  56. 6 22
      src/main/frontend/components/window_controls.cljs
  57. 14 10
      src/main/frontend/config.cljs
  58. 1 1
      src/main/frontend/extensions/code.cljs
  59. 18 15
      src/main/frontend/extensions/pdf/core.cljs
  60. 4 10
      src/main/frontend/extensions/video/youtube.cljs
  61. 1 1
      src/main/frontend/handler/dnd.cljs
  62. 5 2
      src/main/frontend/handler/editor.cljs
  63. 2 11
      src/main/frontend/handler/web/nfs.cljs
  64. 2 2
      src/main/frontend/handler/whiteboard.cljs
  65. 19 0
      src/main/frontend/handler/window.cljs
  66. 7 0
      src/main/frontend/modules/shortcut/config.cljs
  67. 22 18
      src/main/frontend/ui.cljs
  68. 3 3
      src/main/frontend/util.cljc
  69. 1 1
      src/main/frontend/version.cljs
  70. 5 1
      src/resources/dicts/en.edn
  71. 38 23
      src/resources/dicts/es.edn
  72. 29 1
      src/resources/dicts/tr.edn
  73. 29 5
      static/yarn.lock
  74. 21 3
      tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx
  75. 1 1
      tldraw/apps/tldraw-logseq/src/styles.css
  76. 7 0
      tldraw/packages/core/src/lib/TLApi/TLApi.ts
  77. 2 0
      tldraw/packages/core/src/lib/TLSettings.ts
  78. 1 0
      tldraw/packages/react/src/components/AppCanvas.tsx
  79. 1 0
      tldraw/packages/react/src/components/Canvas/Canvas.tsx
  80. 20 0
      tldraw/packages/react/src/hooks/useCanvasEvents.ts
  81. 22 0
      tldraw/packages/react/src/hooks/useShapeEvents.ts
  82. 373 420
      yarn.lock

+ 1 - 1
.github/workflows/build-android.yml

@@ -43,7 +43,7 @@ on:
 env:
 env:
   CLOJURE_VERSION: '1.10.1.763'
   CLOJURE_VERSION: '1.10.1.763'
   NODE_VERSION: '18'
   NODE_VERSION: '18'
-  JAVA_VERSION: '11'
+  JAVA_VERSION: '17'
 
 
 jobs:
 jobs:
   build-apk:
   build-apk:

+ 3 - 2
android/app/build.gradle

@@ -1,13 +1,14 @@
 apply plugin: 'com.android.application'
 apply plugin: 'com.android.application'
 
 
 android {
 android {
+    namespace "com.logseq.app"
     compileSdkVersion rootProject.ext.compileSdkVersion
     compileSdkVersion rootProject.ext.compileSdkVersion
     defaultConfig {
     defaultConfig {
         applicationId "com.logseq.app"
         applicationId "com.logseq.app"
         minSdkVersion rootProject.ext.minSdkVersion
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
-        versionCode 70
-        versionName "0.9.17"
+        versionCode 71
+        versionName "0.9.18"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         aaptOptions {
         aaptOptions {
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

+ 3 - 3
android/app/capacitor.build.gradle

@@ -2,8 +2,8 @@
 
 
 android {
 android {
   compileOptions {
   compileOptions {
-      sourceCompatibility JavaVersion.VERSION_11
-      targetCompatibility JavaVersion.VERSION_11
+      sourceCompatibility JavaVersion.VERSION_17
+      targetCompatibility JavaVersion.VERSION_17
   }
   }
 }
 }
 
 
@@ -19,7 +19,7 @@ dependencies {
     implementation project(':capacitor-splash-screen')
     implementation project(':capacitor-splash-screen')
     implementation project(':capacitor-status-bar')
     implementation project(':capacitor-status-bar')
     implementation project(':capawesome-capacitor-background-task')
     implementation project(':capawesome-capacitor-background-task')
-    implementation project(':hugotomazi-capacitor-navigation-bar')
+    implementation project(':capgo-capacitor-navigation-bar')
     implementation project(':logseq-capacitor-file-sync')
     implementation project(':logseq-capacitor-file-sync')
     implementation project(':capacitor-voice-recorder')
     implementation project(':capacitor-voice-recorder')
     implementation project(':send-intent')
     implementation project(':send-intent')

+ 7 - 5
android/app/src/main/AndroidManifest.xml

@@ -1,7 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.logseq.app">
-
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
     <application
     <application
         android:allowBackup="true"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:icon="@mipmap/ic_launcher"
@@ -37,7 +35,7 @@
                 <action android:name="android.intent.action.VIEW" />
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="logseq" android:host="auth-callback" />
+                <data android:scheme="logseq" />
             </intent-filter>
             </intent-filter>
 
 
         </activity>
         </activity>
@@ -56,7 +54,11 @@
     <!-- Permissions -->
     <!-- Permissions -->
 
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
 </manifest>
 </manifest>

+ 2 - 2
android/app/src/main/assets/capacitor.plugins.json

@@ -40,8 +40,8 @@
 		"classpath": "io.capawesome.capacitorjs.plugins.backgroundtask.BackgroundTaskPlugin"
 		"classpath": "io.capawesome.capacitorjs.plugins.backgroundtask.BackgroundTaskPlugin"
 	},
 	},
 	{
 	{
-		"pkg": "@hugotomazi/capacitor-navigation-bar",
-		"classpath": "br.com.tombus.capacitor.plugin.navigationbar.NavigationBarPlugin"
+		"pkg": "@capgo/capacitor-navigation-bar",
+		"classpath": "ee.forgr.capacitor_navigation_bar.NavigationBarPlugin"
 	},
 	},
 	{
 	{
 		"pkg": "@logseq/capacitor-file-sync",
 		"pkg": "@logseq/capacitor-file-sync",

+ 1 - 1
android/app/src/main/java/com/logseq/app/FolderPicker.java

@@ -43,7 +43,7 @@ public class FolderPicker extends Plugin {
             startActivityForResult(call, i, "folderPickerResult");
             startActivityForResult(call, i, "folderPickerResult");
         } else {
         } else {
             Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
             Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
-            Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
+            Uri uri = Uri.fromParts("package", this.getContext().getPackageName(), null);
             intent.setData(uri);
             intent.setData(uri);
             startActivityForResult(call, intent, 20);
             startActivityForResult(call, intent, 20);
         }
         }

+ 2 - 2
android/build.gradle

@@ -8,8 +8,8 @@ buildscript {
         mavenCentral()
         mavenCentral()
     }
     }
     dependencies {
     dependencies {
-        classpath 'com.android.tools.build:gradle:7.2.1'
-        classpath 'com.google.gms:google-services:4.3.13'
+        classpath 'com.android.tools.build:gradle:8.1.1'
+        classpath 'com.google.gms:google-services:4.3.15'
 
 
         // NOTE: Do not place your application dependencies here; they belong
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
         // in the individual module build.gradle files

+ 2 - 2
android/capacitor.settings.gradle

@@ -32,8 +32,8 @@ project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacit
 include ':capawesome-capacitor-background-task'
 include ':capawesome-capacitor-background-task'
 project(':capawesome-capacitor-background-task').projectDir = new File('../node_modules/@capawesome/capacitor-background-task/android')
 project(':capawesome-capacitor-background-task').projectDir = new File('../node_modules/@capawesome/capacitor-background-task/android')
 
 
-include ':hugotomazi-capacitor-navigation-bar'
-project(':hugotomazi-capacitor-navigation-bar').projectDir = new File('../node_modules/@hugotomazi/capacitor-navigation-bar/android')
+include ':capgo-capacitor-navigation-bar'
+project(':capgo-capacitor-navigation-bar').projectDir = new File('../node_modules/@capgo/capacitor-navigation-bar/android')
 
 
 include ':logseq-capacitor-file-sync'
 include ':logseq-capacitor-file-sync'
 project(':logseq-capacitor-file-sync').projectDir = new File('../node_modules/@logseq/capacitor-file-sync/android')
 project(':logseq-capacitor-file-sync').projectDir = new File('../node_modules/@logseq/capacitor-file-sync/android')

+ 1 - 2
android/gradle.properties

@@ -20,5 +20,4 @@ org.gradle.jvmargs=-Xmx4096m
 # Android operating system, and which are packaged with your app's APK
 # Android operating system, and which are packaged with your app's APK
 # https://developer.android.com/topic/libraries/support-library/androidx-rn
 # https://developer.android.com/topic/libraries/support-library/androidx-rn
 android.useAndroidX=true
 android.useAndroidX=true
-# Automatically convert third-party libraries to use AndroidX
-android.enableJetifier=true
+

+ 1 - 1
android/gradle/wrapper/gradle-wrapper.properties

@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
 zipStorePath=wrapper/dists

+ 10 - 10
android/variables.gradle

@@ -1,16 +1,16 @@
 ext {
 ext {
     minSdkVersion = 22
     minSdkVersion = 22
-    compileSdkVersion = 32
-    targetSdkVersion = 32
-    androidxActivityVersion = '1.4.0'
-    androidxAppCompatVersion = '1.4.2'
+    compileSdkVersion = 33
+    targetSdkVersion = 33
+    androidxActivityVersion = '1.7.0'
+    androidxAppCompatVersion = '1.6.1'
     androidxCoordinatorLayoutVersion = '1.2.0'
     androidxCoordinatorLayoutVersion = '1.2.0'
-    androidxCoreVersion = '1.8.0'
-    androidxFragmentVersion = '1.4.1'
+    androidxCoreVersion = '1.10.0'
+    androidxFragmentVersion = '1.5.6'
     junitVersion = '4.13.2'
     junitVersion = '4.13.2'
-    androidxJunitVersion = '1.1.3'
-    androidxEspressoCoreVersion = '3.4.0'
+    androidxJunitVersion = '1.1.5'
+    androidxEspressoCoreVersion = '3.5.1'
     cordovaAndroidVersion = '10.1.1'
     cordovaAndroidVersion = '10.1.1'
-    coreSplashScreenVersion = '1.0.0-rc01'
-    androidxWebkitVersion = '1.4.0'
+    coreSplashScreenVersion = '1.0.0'
+    androidxWebkitVersion = '1.6.1'
 }
 }

+ 4 - 0
capacitor.config.ts

@@ -9,6 +9,10 @@ const config: CapacitorConfig = {
   bundledWebRuntime: false,
   bundledWebRuntime: false,
   webDir: 'public',
   webDir: 'public',
   loggingBehavior: 'debug',
   loggingBehavior: 'debug',
+  server: {
+    // https://capacitorjs.com/docs/updating/5-0#update-androidscheme
+    androidScheme: 'http',
+  },
   plugins: {
   plugins: {
     SplashScreen: {
     SplashScreen: {
       launchShowDuration: 500,
       launchShowDuration: 500,

+ 1 - 1
deps.edn

@@ -4,7 +4,7 @@
   rum/rum                               {:mvn/version "0.12.9"}
   rum/rum                               {:mvn/version "0.12.9"}
   datascript/datascript                 {:mvn/version "1.3.8"}
   datascript/datascript                 {:mvn/version "1.3.8"}
   datascript-transit/datascript-transit {:mvn/version "0.3.0"}
   datascript-transit/datascript-transit {:mvn/version "0.3.0"}
-  borkdude/rewrite-edn                  {:mvn/version "0.4.6"}
+  borkdude/rewrite-edn                  {:mvn/version "0.4.7"}
   funcool/promesa                       {:mvn/version "4.0.2"}
   funcool/promesa                       {:mvn/version "4.0.2"}
   medley/medley                         {:mvn/version "1.4.0"}
   medley/medley                         {:mvn/version "1.4.0"}
   metosin/reitit-frontend               {:mvn/version "0.3.10"}
   metosin/reitit-frontend               {:mvn/version "0.3.10"}

+ 1 - 0
e2e-tests/accessibility.spec.ts

@@ -8,6 +8,7 @@ test('should not have any automatically detectable accessibility issues', async
     await page.waitForTimeout(2000)
     await page.waitForTimeout(2000)
     const accessibilityScanResults = await new AxeBuilder({ page })
     const accessibilityScanResults = await new AxeBuilder({ page })
         .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
         .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
+        .disableRules(['meta-viewport'])
         .setLegacyMode()
         .setLegacyMode()
         .analyze()
         .analyze()
 
 

+ 1 - 1
ios/.gitignore

@@ -1,9 +1,9 @@
 App/build
 App/build
 App/Pods
 App/Pods
-App/Podfile.lock
 App/App/public
 App/App/public
 DerivedData
 DerivedData
 xcuserdata
 xcuserdata
 
 
 # Cordova plugins for Capacitor
 # Cordova plugins for Capacitor
 capacitor-cordova-ios-plugins
 capacitor-cordova-ios-plugins
+

+ 4 - 4
ios/App/App.xcodeproj/project.pbxproj

@@ -519,7 +519,7 @@
 				INFOPLIST_FILE = App/Info.plist;
 				INFOPLIST_FILE = App/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				MARKETING_VERSION = 0.9.17;
+				MARKETING_VERSION = 0.9.18;
 				OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
 				OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -546,7 +546,7 @@
 				INFOPLIST_FILE = App/Info.plist;
 				INFOPLIST_FILE = App/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				MARKETING_VERSION = 0.9.17;
+				MARKETING_VERSION = 0.9.18;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
@@ -571,7 +571,7 @@
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				MARKETING_VERSION = 0.9.17;
+				MARKETING_VERSION = 0.9.18;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
@@ -598,7 +598,7 @@
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				MARKETING_VERSION = 0.9.17;
+				MARKETING_VERSION = 0.9.18;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";

BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


BIN
ios/App/App/Assets.xcassets/AppIcon.appiconset/[email protected]


+ 11 - 113
ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,116 +1,14 @@
 {
 {
-  "images" : [
-    {
-      "size" : "20x20",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "20x20",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "3x"
-    },
-    {
-      "size" : "29x29",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "29x29",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "3x"
-    },
-    {
-      "size" : "40x40",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "40x40",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "3x"
-    },
-    {
-      "size" : "60x60",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "60x60",
-      "idiom" : "iphone",
-      "filename" : "[email protected]",
-      "scale" : "3x"
-    },
-    {
-      "size" : "20x20",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "1x"
-    },
-    {
-      "size" : "20x20",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "29x29",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "1x"
-    },
-    {
-      "size" : "29x29",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "40x40",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "1x"
-    },
-    {
-      "size" : "40x40",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "76x76",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "1x"
-    },
-    {
-      "size" : "76x76",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "83.5x83.5",
-      "idiom" : "ipad",
-      "filename" : "[email protected]",
-      "scale" : "2x"
-    },
-    {
-      "size" : "1024x1024",
-      "idiom" : "ios-marketing",
-      "filename" : "[email protected]",
-      "scale" : "1x"
+    "images" : [
+      {
+        "filename" : "[email protected]",
+        "idiom" : "universal",
+        "platform" : "ios",
+        "size" : "1024x1024"
+      }
+    ],
+    "info" : {
+      "author" : "xcode",
+      "version" : 1
     }
     }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
 }
 }

+ 1 - 1
ios/App/Podfile

@@ -21,7 +21,7 @@ def capacitor_pods
   pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
   pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
   pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
   pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
   pod 'CapawesomeCapacitorBackgroundTask', :path => '../../node_modules/@capawesome/capacitor-background-task'
   pod 'CapawesomeCapacitorBackgroundTask', :path => '../../node_modules/@capawesome/capacitor-background-task'
-  pod 'HugotomaziCapacitorNavigationBar', :path => '../../node_modules/@hugotomazi/capacitor-navigation-bar'
+  pod 'CapgoCapacitorNavigationBar', :path => '../../node_modules/@capgo/capacitor-navigation-bar'
   pod 'LogseqCapacitorFileSync', :path => '../../node_modules/@logseq/capacitor-file-sync'
   pod 'LogseqCapacitorFileSync', :path => '../../node_modules/@logseq/capacitor-file-sync'
   pod 'CapacitorVoiceRecorder', :path => '../../node_modules/capacitor-voice-recorder'
   pod 'CapacitorVoiceRecorder', :path => '../../node_modules/capacitor-voice-recorder'
   pod 'SendIntent', :path => '../../node_modules/send-intent'
   pod 'SendIntent', :path => '../../node_modules/send-intent'

+ 27 - 19
package.json

@@ -5,7 +5,7 @@
     "main": "static/electron.js",
     "main": "static/electron.js",
     "devDependencies": {
     "devDependencies": {
         "@axe-core/playwright": "=4.4.4",
         "@axe-core/playwright": "=4.4.4",
-        "@capacitor/cli": "^4.0.0",
+        "@capacitor/cli": "^5.0.0",
         "@playwright/test": "=1.31.0",
         "@playwright/test": "=1.31.0",
         "@tailwindcss/aspect-ratio": "0.4.2",
         "@tailwindcss/aspect-ratio": "0.4.2",
         "@tailwindcss/forms": "0.5.3",
         "@tailwindcss/forms": "0.5.3",
@@ -76,26 +76,26 @@
         "postinstall": "yarn tldraw:build && yarn amplify:build "
         "postinstall": "yarn tldraw:build && yarn amplify:build "
     },
     },
     "dependencies": {
     "dependencies": {
-        "@capacitor/android": "^4.0.0",
-        "@capacitor/app": "^4.0.0",
-        "@capacitor/camera": "^4.0.0",
-        "@capacitor/clipboard": "^4.0.0",
-        "@capacitor/core": "^4.0.0",
-        "@capacitor/filesystem": "^4.0.0",
-        "@capacitor/haptics": "^4.0.0",
-        "@capacitor/ios": "^4.0.0",
-        "@capacitor/keyboard": "^4.0.0",
-        "@capacitor/share": "^4.0.0",
-        "@capacitor/splash-screen": "^4.0.0",
-        "@capacitor/status-bar": "^4.0.0",
-        "@capawesome/capacitor-background-task": "^2.0.0",
+        "@capacitor/android": "^5.0.0",
+        "@capacitor/app": "^5.0.0",
+        "@capacitor/camera": "^5.0.0",
+        "@capacitor/clipboard": "^5.0.0",
+        "@capacitor/core": "^5.0.0",
+        "@capacitor/filesystem": "^5.0.0",
+        "@capacitor/haptics": "^5.0.0",
+        "@capacitor/ios": "^5.0.0",
+        "@capacitor/keyboard": "^5.0.0",
+        "@capacitor/share": "^5.0.0",
+        "@capacitor/splash-screen": "^5.0.0",
+        "@capacitor/status-bar": "^5.0.0",
+        "@capawesome/capacitor-background-task": "^5.0.0",
         "@emoji-mart/data": "^1.1.2",
         "@emoji-mart/data": "^1.1.2",
         "@emoji-mart/react": "^1.1.1",
         "@emoji-mart/react": "^1.1.1",
         "@excalidraw/excalidraw": "0.15.3",
         "@excalidraw/excalidraw": "0.15.3",
         "@highlightjs/cdn-assets": "10.4.1",
         "@highlightjs/cdn-assets": "10.4.1",
-        "@hugotomazi/capacitor-navigation-bar": "^2.0.0",
+        "@capgo/capacitor-navigation-bar": "^6.0.0",
         "@isomorphic-git/lightning-fs": "^4.6.0",
         "@isomorphic-git/lightning-fs": "^4.6.0",
-        "@logseq/capacitor-file-sync": "0.0.35",
+        "@logseq/capacitor-file-sync": "5.0.0",
         "@logseq/diff-merge": "0.2.2",
         "@logseq/diff-merge": "0.2.2",
         "@logseq/react-tweet-embed": "1.3.1-1",
         "@logseq/react-tweet-embed": "1.3.1-1",
         "@radix-ui/colors": "^0.1.8",
         "@radix-ui/colors": "^0.1.8",
@@ -104,11 +104,11 @@
         "@tabler/icons": "^1.96.0",
         "@tabler/icons": "^1.96.0",
         "@tippyjs/react": "4.2.5",
         "@tippyjs/react": "4.2.5",
         "bignumber.js": "^9.0.2",
         "bignumber.js": "^9.0.2",
-        "capacitor-voice-recorder": "4.0.0",
+        "capacitor-voice-recorder": "^5.0.0",
         "check-password-strength": "2.0.7",
         "check-password-strength": "2.0.7",
         "chokidar": "3.5.1",
         "chokidar": "3.5.1",
         "chrono-node": "2.2.4",
         "chrono-node": "2.2.4",
-        "codemirror": "5.58.1",
+        "codemirror": "5.65.13",
         "comlink": "^4.4.1",
         "comlink": "^4.4.1",
         "d3-force": "3.0.0",
         "d3-force": "3.0.0",
         "diff": "5.0.0",
         "diff": "5.0.0",
@@ -147,7 +147,7 @@
         "remove-accents": "0.4.2",
         "remove-accents": "0.4.2",
         "reveal.js": "^4.5.0",
         "reveal.js": "^4.5.0",
         "sanitize-filename": "1.6.3",
         "sanitize-filename": "1.6.3",
-        "send-intent": "3.0.11",
+        "send-intent": "^5.0.0",
         "shepherd.js": "^9.1.0",
         "shepherd.js": "^9.1.0",
         "tailwind-capitalize-first-letter": "^1.0.4",
         "tailwind-capitalize-first-letter": "^1.0.4",
         "threads": "1.6.5",
         "threads": "1.6.5",
@@ -155,6 +155,14 @@
         "yargs-parser": "20.2.4"
         "yargs-parser": "20.2.4"
     },
     },
     "resolutions": {
     "resolutions": {
+        "**/postcss": "8.4.17",
+        "**/postcss-colormin": "5.3.0",
+        "**/postcss-convert-values": "5.1.2",
+        "**/postcss-js": "4.0.0",
+        "**/postcss-merge-longhand": "5.1.6",
+        "**/postcss-merge-rules": "5.1.2",
+        "**/postcss-minify-params": "5.1.3",
+        "**/postcss-reduce-initial": "5.1.0",
         "pixi-graph-fork/@pixi/app": "6.2.0",
         "pixi-graph-fork/@pixi/app": "6.2.0",
         "pixi-graph-fork/@pixi/constants": "6.2.0",
         "pixi-graph-fork/@pixi/constants": "6.2.0",
         "pixi-graph-fork/@pixi/core": "6.2.0",
         "pixi-graph-fork/@pixi/core": "6.2.0",

+ 1 - 1
resources/forge.config.js

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

+ 11 - 5
resources/js/preload.js

@@ -116,15 +116,21 @@ contextBridge.exposeInMainWorld('apis', {
 
 
     const dest = path.join(repoPathRoot, to)
     const dest = path.join(repoPathRoot, to)
     const assetsRoot = path.dirname(dest)
     const assetsRoot = path.dirname(dest)
-    
+
     await fs.promises.mkdir(assetsRoot, { recursive: true })
     await fs.promises.mkdir(assetsRoot, { recursive: true })
 
 
-    from = from && decodeURIComponent(from || getFilePathFromClipboard())
+    from = from || getFilePathFromClipboard()
 
 
     if (from) {
     if (from) {
-      // console.debug('copy file: ', from, dest)
-      await fs.promises.copyFile(from, dest)
-      return path.basename(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
     // support image

+ 3 - 2
resources/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "Logseq",
   "name": "Logseq",
   "productName": "Logseq",
   "productName": "Logseq",
-  "version": "0.9.17",
+  "version": "0.9.18",
   "main": "electron.js",
   "main": "electron.js",
   "author": "Logseq",
   "author": "Logseq",
   "license": "AGPL-3.0",
   "license": "AGPL-3.0",
@@ -34,7 +34,8 @@
     "update-electron-app": "2.0.1",
     "update-electron-app": "2.0.1",
     "extract-zip": "2.0.1",
     "extract-zip": "2.0.1",
     "diff-match-patch": "1.0.5",
     "diff-match-patch": "1.0.5",
-    "https-proxy-agent": "5.0.0",
+    "https-proxy-agent": "7.0.2",
+    "socks-proxy-agent": "8.0.2",
     "@sentry/electron": "2.5.1",
     "@sentry/electron": "2.5.1",
     "posthog-js": "1.10.2",
     "posthog-js": "1.10.2",
     "@logseq/rsapi": "0.0.73",
     "@logseq/rsapi": "0.0.73",

+ 7 - 7
src/electron/electron/configs.cljs

@@ -1,9 +1,9 @@
 (ns electron.configs
 (ns electron.configs
-  (:require
-    ["fs-extra" :as ^js fs]
-    ["path" :as ^js node-path]
-    ["electron" :refer [^js app] :as electron]
-    [cljs.reader :as reader]))
+  (:require ["electron" :refer [^js app] :as electron]
+            ["fs-extra" :as ^js fs]
+            ["path" :as ^js node-path]
+            [cljs.reader :as reader]
+            [electron.logger :as logger]))
 
 
 ;; FIXME: move configs.edn to where it should be
 ;; FIXME: move configs.edn to where it should be
 (defonce dot-root (.join node-path (.getPath app "home") ".logseq"))
 (defonce dot-root (.join node-path (.getPath app "home") ".logseq"))
@@ -17,14 +17,14 @@
     (let [body (.toString (.readFileSync fs cfg-path))]
     (let [body (.toString (.readFileSync fs cfg-path))]
       (if (seq body) (reader/read-string body) {}))
       (if (seq body) (reader/read-string body) {}))
     (catch :default e
     (catch :default e
-      (js/console.error :cfg-error e))))
+      (logger/error :cfg-error e))))
 
 
 (defn- write-cfg!
 (defn- write-cfg!
   [cfg]
   [cfg]
   (try
   (try
     (.writeFileSync fs cfg-path (pr-str cfg)) cfg
     (.writeFileSync fs cfg-path (pr-str cfg)) cfg
     (catch :default e
     (catch :default e
-      (js/console.error :cfg-error e))))
+      (logger/error :cfg-error e))))
 
 
 (defn set-item!
 (defn set-item!
   [k v]
   [k v]

+ 4 - 0
src/electron/electron/core.cljs

@@ -208,6 +208,10 @@
                                     {:role "about"
                                     {:role "about"
                                      :label "About Logseq"
                                      :label "About Logseq"
                                      :click about-fn}]}))
                                      :click about-fn}]}))
+        ;; Enable Cmd/Ctrl+= Zoom In
+        template (conj template 
+                       {:role "zoomin"
+                        :accelerator "CommandOrControl+="})
         menu (.buildFromTemplate Menu (clj->js template))]
         menu (.buildFromTemplate Menu (clj->js template))]
     (.setApplicationMenu Menu menu)))
     (.setApplicationMenu Menu menu)))
 
 

+ 13 - 2
src/electron/electron/handler.cljs

@@ -6,6 +6,7 @@
             ["buffer" :as buffer]
             ["buffer" :as buffer]
             ["diff-match-patch" :as google-diff]
             ["diff-match-patch" :as google-diff]
             ["electron" :refer [app autoUpdater dialog ipcMain shell]]
             ["electron" :refer [app autoUpdater dialog ipcMain shell]]
+            ["electron-window-state" :as windowStateKeeper]
             ["fs" :as fs]
             ["fs" :as fs]
             ["fs-extra" :as fs-extra]
             ["fs-extra" :as fs-extra]
             ["os" :as os]
             ["os" :as os]
@@ -98,6 +99,12 @@
     (catch :default _e
     (catch :default _e
       false)))
       false)))
 
 
+(defn chmod-enabled?
+  []
+  (if (= nil (cfgs/get-item :feature/enable-automatic-chmod?))
+    true
+    (cfgs/get-item :feature/enable-automatic-chmod?)))
+
 (defmethod handle :copyFile [_window [_ _repo from-path to-path]]
 (defmethod handle :copyFile [_window [_ _repo from-path to-path]]
   (logger/info ::copy-file from-path to-path)
   (logger/info ::copy-file from-path to-path)
   (fs-extra/copy from-path to-path))
   (fs-extra/copy from-path to-path))
@@ -108,7 +115,7 @@
                       (.from Buf content)
                       (.from Buf content)
                       content)]
                       content)]
     (try
     (try
-      (when (and (fs/existsSync path) (not (writable? path)))
+      (when (and (chmod-enabled?) (fs/existsSync path) (not (writable? path)))
         (fs/chmodSync path "644"))
         (fs/chmodSync path "644"))
       (fs/writeFileSync path content)
       (fs/writeFileSync path content)
       (fs/statSync path)
       (fs/statSync path)
@@ -269,7 +276,7 @@
                                   (.toString (.readFileSync fs txid-path)))]
                                   (.toString (.readFileSync fs txid-path)))]
           (reader/read-string sync-meta))))
           (reader/read-string sync-meta))))
     (catch :default e
     (catch :default e
-      (js/console.debug "[read txid meta] #" root (.-message e)))))
+      (logger/error "[read txid meta] #" root (.-message e)))))
 
 
 (defmethod handle :inflateGraphsInfo [_win [_ graphs]]
 (defmethod handle :inflateGraphsInfo [_win [_ graphs]]
   (if (seq graphs)
   (if (seq graphs)
@@ -671,6 +678,10 @@
 (defmethod handle :window-close [^js win]
 (defmethod handle :window-close [^js win]
   (.close win))
   (.close win))
 
 
+(defmethod handle :theme-loaded [^js win]
+  (.manage (windowStateKeeper) win)
+  (.show win))
+
 ;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;;;;;;;;;;;;;;;;;;
 ;; file-sync-rs-apis ;;
 ;; file-sync-rs-apis ;;
 ;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;;;;;;;;;;;;;;;;;;

+ 8 - 2
src/electron/electron/utils.cljs

@@ -26,7 +26,8 @@
 (defonce *fetchAgent (atom nil))
 (defonce *fetchAgent (atom nil))
 
 
 (defonce open (js/require "open"))
 (defonce open (js/require "open"))
-(defonce HttpsProxyAgent (js/require "https-proxy-agent"))
+(defonce HttpsProxyAgent (.-HttpsProxyAgent (js/require "https-proxy-agent")))
+(defonce SocksProxyAgent (.-SocksProxyAgent (js/require "socks-proxy-agent")))
 (defonce _fetch (js/require "node-fetch"))
 (defonce _fetch (js/require "node-fetch"))
 (defonce extract-zip (js/require "extract-zip"))
 (defonce extract-zip (js/require "extract-zip"))
 
 
@@ -67,7 +68,12 @@
   [{:keys [protocol host port]}]
   [{:keys [protocol host port]}]
   (if (and protocol host port (or (= protocol "http") (= protocol "socks5")))
   (if (and protocol host port (or (= protocol "http") (= protocol "socks5")))
     (let [proxy-url (str protocol "://" host ":" port)]
     (let [proxy-url (str protocol "://" host ":" port)]
-      (reset! *fetchAgent (new HttpsProxyAgent proxy-url)))
+      (condp = protocol
+        "http"
+        (reset! *fetchAgent (new HttpsProxyAgent proxy-url))
+        "socks5"
+        (reset! *fetchAgent (new SocksProxyAgent proxy-url))
+        (logger/error "Unknown proxy protocol:" protocol)))
     (reset! *fetchAgent nil)))
     (reset! *fetchAgent nil)))
 
 
 (defn- set-rsapi-proxy
 (defn- set-rsapi-proxy

+ 1 - 1
src/electron/electron/window.cljs

@@ -35,6 +35,7 @@
                       :titleBarStyle        "hiddenInset"
                       :titleBarStyle        "hiddenInset"
                       :trafficLightPosition {:x 16 :y 16}
                       :trafficLightPosition {:x 16 :y 16}
                       :autoHideMenuBar      (not mac?)
                       :autoHideMenuBar      (not mac?)
+                      :show                 false
                       :webPreferences
                       :webPreferences
                       {:plugins                 true        ; pdf
                       {:plugins                 true        ; pdf
                        :nodeIntegration         false
                        :nodeIntegration         false
@@ -55,7 +56,6 @@
                      linux?
                      linux?
                      (assoc :icon (node-path/join js/__dirname "icons/logseq.png")))
                      (assoc :icon (node-path/join js/__dirname "icons/logseq.png")))
          win       (BrowserWindow. (clj->js win-opts))]
          win       (BrowserWindow. (clj->js win-opts))]
-     (.manage win-state win)
      (.onBeforeSendHeaders (.. session -defaultSession -webRequest)
      (.onBeforeSendHeaders (.. session -defaultSession -webRequest)
                            (clj->js {:urls (array "*://*.youtube.com/*")})
                            (clj->js {:urls (array "*://*.youtube.com/*")})
                            (fn [^js details callback]
                            (fn [^js details callback]

+ 1 - 1
src/main/frontend/components/block.cljs

@@ -1351,7 +1351,7 @@
                   (str "https://player.vimeo.com/video/" id)
                   (str "https://player.vimeo.com/video/" id)
 
 
                   [_ _ _ "bilibili.com" _ id & query]
                   [_ _ _ "bilibili.com" _ id & query]
-                  (str "https://player.bilibili.com/player.html?bvid=" id "&high_quality=1"
+                  (str "https://player.bilibili.com/player.html?bvid=" id "&high_quality=1&autoplay=0"
                        (when-let [page (second query)]
                        (when-let [page (second query)]
                          (str "&page=" page)))
                          (str "&page=" page)))
 
 

+ 2 - 2
src/main/frontend/components/bug_report.cljs

@@ -73,7 +73,7 @@
          (ui/button (t :bug-report/inspector-page-btn-copy) :on-click #(copy-result-to-clipboard! (js/JSON.stringify (clj->js result) nil 2)))]
          (ui/button (t :bug-report/inspector-page-btn-copy) :on-click #(copy-result-to-clipboard! (js/JSON.stringify (clj->js result) nil 2)))]
         [:div.flex.justify-between.items-center.mt-2
         [:div.flex.justify-between.items-center.mt-2
          [:div (t :bug-report/inspector-page-desc-create-issue)]
          [:div (t :bug-report/inspector-page-desc-create-issue)]
-         (ui/button (t :bug-report/inspector-page-btn-create-issue) :href header/bug-report-url)]
+         (ui/button (t :bug-report/inspector-page-btn-create-issue) :href (header/bug-report-url))]
         [:div.flex.justify-between.items-center.mt-2
         [:div.flex.justify-between.items-center.mt-2
          [:div (t :bug-report/inspector-page-tip)]
          [:div (t :bug-report/inspector-page-tip)]
          (ui/button (t :bug-report/inspector-page-btn-back) :on-click reset-step!)]
          (ui/button (t :bug-report/inspector-page-btn-back) :on-click reset-step!)]
@@ -118,4 +118,4 @@
     [:div.flex.flex-col
     [:div.flex.flex-col
      [:h1.text-2xl (t :bug-report/section-issues-title)]
      [:h1.text-2xl (t :bug-report/section-issues-title)]
      [:div.opacity-60 (t :bug-report/section-issues-desc)]
      [:div.opacity-60 (t :bug-report/section-issues-desc)]
-     (report-item-button (t :bug-report/section-issues-btn-title) (t :bug-report/section-issues-btn-desc) "message-report" {:on-click #(util/open-url header/bug-report-url)})]]])
+     (report-item-button (t :bug-report/section-issues-btn-title) (t :bug-report/section-issues-btn-desc) "message-report" {:on-click #(util/open-url (header/bug-report-url))})]]])

+ 1 - 1
src/main/frontend/components/container.css

@@ -524,7 +524,7 @@ html[data-theme='dark'] {
   }
   }
 
 
   &-btn {
   &-btn {
-    @apply fixed bottom-4 right-8;
+    @apply fixed bottom-4 right-4 sm:right-8;
 
 
     > .inner {
     > .inner {
       @apply font-bold
       @apply font-bold

+ 22 - 18
src/main/frontend/components/editor.cljs

@@ -479,16 +479,6 @@
         right-sidebar? (:ui/sidebar-open? @state/state)
         right-sidebar? (:ui/sidebar-open? @state/state)
         editing-key    (state/get-edit-input-id)
         editing-key    (state/get-edit-input-id)
         *el (rum/use-ref nil)
         *el (rum/use-ref nil)
-        _ (rum/use-effect! (fn []
-                             (when-let [^js/HTMLElement cnt
-                                        (and right-sidebar? editing-key
-                                             (js/document.querySelector "#main-content-container"))]
-                               (when (.contains cnt (js/document.querySelector (str "#" editing-key)))
-                                 (let [el  (rum/deref *el)
-                                       ofx (- (.-scrollWidth cnt) (.-clientWidth cnt))]
-                                   (when (> ofx 0)
-                                     (set! (.-transform (.-style el)) (str "translateX(-" (+ ofx 20) "px)")))))))
-                           [right-sidebar? editing-key])
         y-overflow-vh? (or (< to-max-height Y-BOUNDARY-HEIGHT)
         y-overflow-vh? (or (< to-max-height Y-BOUNDARY-HEIGHT)
                            (> (- max-height' to-max-height) Y-BOUNDARY-HEIGHT))
                            (> (- max-height' to-max-height) Y-BOUNDARY-HEIGHT))
         to-max-height (if y-overflow-vh? max-height' to-max-height)
         to-max-height (if y-overflow-vh? max-height' to-max-height)
@@ -498,22 +488,36 @@
         style (merge
         style (merge
                {:top        (+ top offset-top (if (int? y-diff) y-diff 0))
                {:top        (+ top offset-top (if (int? y-diff) y-diff 0))
                 :max-height to-max-height
                 :max-height to-max-height
-                :max-width 700
+                :max-width  700
                 ;; TODO: auto responsive fixed size
                 ;; TODO: auto responsive fixed size
-                :width "fit-content"
+                :width      "fit-content"
                 :z-index    11}
                 :z-index    11}
                (when set-default-width?
                (when set-default-width?
                  {:width max-width})
                  {:width max-width})
                (if (<= vw-max-width (+ left (if set-default-width? max-width 500)))
                (if (<= vw-max-width (+ left (if set-default-width? max-width 500)))
                  {:right 0}
                  {:right 0}
-                 {:left (if (or (nil? y-diff) (and y-diff (= y-diff 0))) left 0)}))]
+                 {:left 0}))]
+
+    (rum/use-effect!
+     (fn []
+       (when-let [^js/HTMLElement cnt
+                  (and right-sidebar? editing-key
+                       (js/document.querySelector "#main-content-container"))]
+         (when (.contains cnt (js/document.querySelector (str "#" editing-key)))
+           (let [el  (rum/deref *el)
+                 ofx (- (.-scrollWidth cnt) (.-clientWidth cnt))]
+             (when (> ofx 0)
+               (set! (.-transform (.-style el))
+                     (util/format "translate(-%spx, %s)" (+ ofx 20) (if y-overflow-vh? "calc(-100% - 2rem)" 0))))))))
+     [right-sidebar? editing-key y-overflow-vh?])
+
     [:div.absolute.rounded-md.shadow-lg.absolute-modal
     [:div.absolute.rounded-md.shadow-lg.absolute-modal
-     {:ref *el
+     {:ref             *el
       :data-modal-name modal-name
       :data-modal-name modal-name
-      :class (if y-overflow-vh? "is-overflow-vh-y" "")
-      :on-mouse-down (fn [e]
-                       (.stopPropagation e))
-      :style style}
+      :class           (if y-overflow-vh? "is-overflow-vh-y" "")
+      :on-mouse-down   (fn [e]
+                         (.stopPropagation e))
+      :style           style}
      cp]))
      cp]))
 
 
 (rum/defc transition-cp < rum/reactive
 (rum/defc transition-cp < rum/reactive

+ 6 - 3
src/main/frontend/components/header.cljs

@@ -62,13 +62,16 @@
       :on-click on-click}
       :on-click on-click}
      (ui/icon "menu-2" {:size ui/icon-size})]))
      (ui/icon "menu-2" {:size ui/icon-size})]))
 
 
-(def bug-report-url
+(defn bug-report-url []
   (let [ua (.-userAgent js/navigator)
   (let [ua (.-userAgent js/navigator)
         safe-ua (string/replace ua #"[^_/a-zA-Z0-9\.\(\)]+" " ")
         safe-ua (string/replace ua #"[^_/a-zA-Z0-9\.\(\)]+" " ")
         platform (str "App Version: " version "\n"
         platform (str "App Version: " version "\n"
                       "Git Revision: " config/REVISION "\n"
                       "Git Revision: " config/REVISION "\n"
                       "Platform: " safe-ua "\n"
                       "Platform: " safe-ua "\n"
-                      "Language: " (.-language js/navigator))]
+                      "Language: " (.-language js/navigator) "\n"
+                      "Plugins: " (string/join ", " (map (fn [[k v]]
+                                                           (str (name k) " (" (:version v) ")"))
+                                                         (:plugin/installed-plugins @state/state))))]
     (str "https://github.com/logseq/logseq/issues/new?"
     (str "https://github.com/logseq/logseq/issues/new?"
          "title=&"
          "title=&"
          "template=bug_report.yaml&"
          "template=bug_report.yaml&"
@@ -114,7 +117,7 @@
           :options {:href (rfe/href :import)}
           :options {:href (rfe/href :import)}
           :icon (ui/icon "file-upload")})
           :icon (ui/icon "file-upload")})
 
 
-       (when-not config/publishing? 
+       (when-not config/publishing?
          {:title [:div.flex-row.flex.justify-between.items-center
          {:title [:div.flex-row.flex.justify-between.items-center
                   [:span (t :join-community)]]
                   [:span (t :join-community)]]
           :options {:href "https://discuss.logseq.com"
           :options {:href "https://discuss.logseq.com"

+ 34 - 12
src/main/frontend/components/page.cljs

@@ -2,18 +2,18 @@
   (:require ["/frontend/utils" :as utils]
   (:require ["/frontend/utils" :as utils]
             [clojure.string :as string]
             [clojure.string :as string]
             [frontend.components.block :as component-block]
             [frontend.components.block :as component-block]
-            [frontend.components.query :as query]
             [frontend.components.content :as content]
             [frontend.components.content :as content]
             [frontend.components.editor :as editor]
             [frontend.components.editor :as editor]
             [frontend.components.hierarchy :as hierarchy]
             [frontend.components.hierarchy :as hierarchy]
             [frontend.components.plugins :as plugins]
             [frontend.components.plugins :as plugins]
+            [frontend.components.query :as query]
             [frontend.components.reference :as reference]
             [frontend.components.reference :as reference]
-            [frontend.components.svg :as svg]
             [frontend.components.scheduled-deadlines :as scheduled]
             [frontend.components.scheduled-deadlines :as scheduled]
             [frontend.components.property :as property]
             [frontend.components.property :as property]
             [frontend.components.property.value :as pv]
             [frontend.components.property.value :as pv]
             [frontend.handler.property.util :as pu]
             [frontend.handler.property.util :as pu]
             [frontend.handler.property :as property-handler]
             [frontend.handler.property :as property-handler]
+            [frontend.components.svg :as svg]
             [frontend.config :as config]
             [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
             [frontend.context.i18n :refer [t]]
             [frontend.date :as date]
             [frontend.date :as date]
@@ -25,6 +25,7 @@
             [frontend.format.block :as block]
             [frontend.format.block :as block]
             [frontend.handler.common :as common-handler]
             [frontend.handler.common :as common-handler]
             [frontend.handler.config :as config-handler]
             [frontend.handler.config :as config-handler]
+            [frontend.handler.dnd :as dnd]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.graph :as graph-handler]
             [frontend.handler.graph :as graph-handler]
             [frontend.handler.notification :as notification]
             [frontend.handler.notification :as notification]
@@ -38,13 +39,14 @@
             [frontend.util :as util]
             [frontend.util :as util]
             [frontend.util.text :as text-util]
             [frontend.util.text :as text-util]
             [goog.object :as gobj]
             [goog.object :as gobj]
+            [logseq.graph-parser.mldoc :as gp-mldoc]
             [logseq.graph-parser.util :as gp-util]
             [logseq.graph-parser.util :as gp-util]
+            [logseq.graph-parser.util.page-ref :as page-ref]
+            [logseq.db.property :as db-property]
             [medley.core :as medley]
             [medley.core :as medley]
+            [promesa.core :as p]
             [reitit.frontend.easy :as rfe]
             [reitit.frontend.easy :as rfe]
-            [rum.core :as rum]
-            [logseq.graph-parser.util.page-ref :as page-ref]
-            [logseq.graph-parser.mldoc :as gp-mldoc]
-            [logseq.db.property :as db-property]))
+            [rum.core :as rum]))
 
 
 (defn- get-page-name
 (defn- get-page-name
   [state]
   [state]
@@ -106,10 +108,26 @@
 
 
   (rum/defc dummy-block
   (rum/defc dummy-block
     [page-name]
     [page-name]
-    (let [handler-fn (fn []
-                       (let [block (editor-handler/insert-first-page-block-if-not-exists! page-name {:redirect? false})]
-                         (js/setTimeout #(editor-handler/edit-block! block :max (:block/uuid block)) 0)))]
-      [:div.ls-block.flex-1.flex-col.rounded-sm {:style {:width "100%"}}
+    (let [[hover set-hover!] (rum/use-state false)
+          click-handler-fn (fn []
+                             (let [block (editor-handler/insert-first-page-block-if-not-exists! page-name {:redirect? false})]
+                               (js/setTimeout #(editor-handler/edit-block! block :max (:block/uuid block)) 0)))
+          drop-handler-fn (fn [^js event]
+                            (util/stop event)
+                            (p/let [block-uuids (state/get-selection-block-ids)
+                                    lookup-refs (map (fn [id] [:block/uuid id]) block-uuids)
+                                    selected (db/pull-many (state/get-current-repo) '[*] lookup-refs)
+                                    blocks (if (seq selected) selected [@component-block/*dragging-block])
+                                    _ (editor-handler/insert-first-page-block-if-not-exists! page-name {:redirect? false})]
+                              (js/setTimeout #(let [target-block (db/pull (:db/id (db/get-page page-name)))]
+                                                (dnd/move-blocks event blocks target-block nil :sibling))
+                                             0)))]
+      [:div.ls-block.flex-1.flex-col.rounded-sm
+       {:style {:width "100%"
+              ;; The same as .dnd-separator
+                :border-top (if hover
+                              "3px solid #ccc"
+                              nil)}}
        [:div.flex.flex-row
        [:div.flex.flex-row
         [:div.flex.flex-row.items-center.mr-2.ml-1 {:style {:height 24}}
         [:div.flex.flex-row.items-center.mr-2.ml-1 {:style {:height 24}}
          [:span.bullet-container.cursor
          [:span.bullet-container.cursor
@@ -117,8 +135,12 @@
         [:div.flex.flex-1 {:tabIndex 0
         [:div.flex.flex-1 {:tabIndex 0
                            :on-key-press (fn [e]
                            :on-key-press (fn [e]
                                            (when (= "Enter" (util/ekey e))
                                            (when (= "Enter" (util/ekey e))
-                                             (handler-fn)))
-                           :on-click handler-fn}
+                                             (click-handler-fn)))
+                           :on-click click-handler-fn
+                           :on-drag-enter #(set-hover! true)
+                           :on-drag-over #(util/stop %)
+                           :on-drop drop-handler-fn
+                           :on-drag-leave #(set-hover! false)}
          [:span.opacity-70
          [:span.opacity-70
           "Click here to edit..."]]]])))
           "Click here to edit..."]]]])))
 
 

+ 2 - 1
src/main/frontend/components/plugins.cljs

@@ -447,9 +447,10 @@
                                  (-> (p/let [result (ipc/ipc :testProxyUrl val opts)]
                                  (-> (p/let [result (ipc/ipc :testProxyUrl val opts)]
                                        (js->clj result :keywordize-keys true))
                                        (js->clj result :keywordize-keys true))
                                      (p/then (fn [{:keys [code response-ms]}]
                                      (p/then (fn [{:keys [code response-ms]}]
+                                               (notification/clear! :proxy-net-check)
                                                (notification/show! (str "Success! Status " code " in " response-ms "ms.") :success)))
                                                (notification/show! (str "Success! Status " code " in " response-ms "ms.") :success)))
                                      (p/catch (fn [e]
                                      (p/catch (fn [e]
-                                                (notification/show! (str e) :error)))
+                                                (notification/show! (str e) :error false :proxy-net-check)))
                                      (p/finally (fn [] (set-testing?! false)))))))]
                                      (p/finally (fn [] (set-testing?! false)))))))]
 
 
       [:p.pt-2
       [:p.pt-2

+ 1 - 0
src/main/frontend/components/right_sidebar.cljs

@@ -383,6 +383,7 @@
                 :aria-label (t :right-side-bar/separator)
                 :aria-label (t :right-side-bar/separator)
                 :aria-valuemin (* min-ratio 100)
                 :aria-valuemin (* min-ratio 100)
                 :aria-valuemax (* max-ratio 100)
                 :aria-valuemax (* max-ratio 100)
+                :aria-valuenow 50
                 :tabIndex "0"
                 :tabIndex "0"
                 :data-expanded sidebar-open?}]))
                 :data-expanded sidebar-open?}]))
 
 

+ 15 - 0
src/main/frontend/components/settings.cljs

@@ -593,6 +593,20 @@
    {:left-label (t :settings-page/network-proxy)
    {:left-label (t :settings-page/network-proxy)
     :action (user-proxy-settings agent-opts)}))
     :action (user-proxy-settings agent-opts)}))
 
 
+(rum/defcs auto-chmod-row < rum/reactive
+  [state t]
+  (let [enabled? (if (= nil (state/sub [:electron/user-cfgs :feature/enable-automatic-chmod?]))
+                   true
+                   (state/sub [:electron/user-cfgs :feature/enable-automatic-chmod?]))]
+    (toggle
+     "automatic-chmod"
+     (t :settings-page/auto-chmod)
+     enabled?
+     #(do
+       (state/set-state! [:electron/user-cfgs :feature/enable-automatic-chmod?] (not enabled?))
+       (ipc/ipc :userAppCfgs :feature/enable-automatic-chmod? (not enabled?)))
+     [:span.text-sm.opacity-50 (t :settings-page/auto-chmod-desc)])))
+
 (defn filename-format-row []
 (defn filename-format-row []
   (row-with-button-action
   (row-with-button-action
    {:left-label (t :settings-page/filename-format)
    {:left-label (t :settings-page/filename-format)
@@ -700,6 +714,7 @@
      (usage-diagnostics-row t instrument-disabled?)
      (usage-diagnostics-row t instrument-disabled?)
      (when-not (mobile-util/native-platform?) (developer-mode-row t developer-mode?))
      (when-not (mobile-util/native-platform?) (developer-mode-row t developer-mode?))
      (when (util/electron?) (https-user-agent-row https-agent-opts))
      (when (util/electron?) (https-user-agent-row https-agent-opts))
+     (when (util/electron?) (auto-chmod-row t))
      (when (and (util/electron?) (not (config/demo-graph? current-repo))) (filename-format-row))
      (when (and (util/electron?) (not (config/demo-graph? current-repo))) (filename-format-row))
      (clear-cache-row t)
      (clear-cache-row t)
 
 

+ 6 - 1
src/main/frontend/components/theme.cljs

@@ -1,5 +1,6 @@
 (ns frontend.components.theme
 (ns frontend.components.theme
-  (:require [frontend.extensions.pdf.core :as pdf]
+  (:require [electron.ipc :as ipc]
+            [frontend.extensions.pdf.core :as pdf]
             [frontend.config :as config]
             [frontend.config :as config]
             [frontend.handler.plugin :as plugin-handler]
             [frontend.handler.plugin :as plugin-handler]
             [frontend.handler.plugin-config :as plugin-config-handler]
             [frontend.handler.plugin-config :as plugin-config-handler]
@@ -35,6 +36,10 @@
      #(let [doc js/document.documentElement]
      #(let [doc js/document.documentElement]
         (.setAttribute doc "lang" preferred-language)))
         (.setAttribute doc "lang" preferred-language)))
 
 
+    (rum/use-effect!
+     #(js/setTimeout (fn [] (ipc/ipc "theme-loaded")) 100) ; Wait for the theme to be applied
+     [])
+
     (rum/use-effect!
     (rum/use-effect!
      #(when (and restored-sidebar?
      #(when (and restored-sidebar?
                  (mounted-fn))
                  (mounted-fn))

+ 1 - 1
src/main/frontend/components/whiteboard.css

@@ -205,7 +205,7 @@ input.tl-text-input {
 
 
   .tl-action-bar {
   .tl-action-bar {
     left: 0.5rem;
     left: 0.5rem;
-    bottom: 0.5rem;
+    bottom: 0;
   }
   }
 
 
   .tl-primary-tools {
   .tl-primary-tools {

+ 6 - 22
src/main/frontend/components/window_controls.cljs

@@ -1,27 +1,11 @@
 (ns frontend.components.window-controls
 (ns frontend.components.window-controls
-  (:require [electron.ipc :as ipc]
-            [frontend.components.svg :as svg]
+  (:require [frontend.components.svg :as svg]
             [frontend.context.i18n :refer [t]]
             [frontend.context.i18n :refer [t]]
+            [frontend.handler.window :as window-handler]
             [frontend.state :as state]
             [frontend.state :as state]
             [frontend.ui :as ui]
             [frontend.ui :as ui]
             [rum.core :as rum]))
             [rum.core :as rum]))
 
 
-(defn minimize
-  []
-  (ipc/ipc "window-minimize"))
-
-(defn toggle-maximized
-  []
-  (ipc/ipc "window-toggle-maximized"))
-
-(defn close
-  []
-  (ipc/ipc "window-close"))
-
-(defn toggle-fullscreen
-  []
-  (ipc/ipc "window-toggle-fullscreen"))
-
 (rum/defc container < rum/reactive
 (rum/defc container < rum/reactive
   []
   []
   (let [maximized?  (state/sub :electron/window-maximized?)
   (let [maximized?  (state/sub :electron/window-maximized?)
@@ -30,23 +14,23 @@
      (if fullscreen?
      (if fullscreen?
        [:button.button.icon.fullscreen-toggle
        [:button.button.icon.fullscreen-toggle
         {:title (t :window/exit-fullscreen)
         {:title (t :window/exit-fullscreen)
-         :on-click toggle-fullscreen}
+         :on-click window-handler/toggle-fullscreen!}
         (ui/icon "arrows-minimize")]
         (ui/icon "arrows-minimize")]
        [:<>
        [:<>
         [:button.button.icon.minimize
         [:button.button.icon.minimize
          {:title (t :window/minimize)
          {:title (t :window/minimize)
-          :on-click minimize}
+          :on-click window-handler/minimize!}
          (svg/window-minimize)]
          (svg/window-minimize)]
 
 
         [:button.button.icon.maximize-toggle
         [:button.button.icon.maximize-toggle
          {:title (if maximized? (t :window/restore) (t :window/maximize))
          {:title (if maximized? (t :window/restore) (t :window/maximize))
           :class (if maximized? "restore" "maximize")
           :class (if maximized? "restore" "maximize")
-          :on-click toggle-maximized}
+          :on-click window-handler/toggle-maximized!}
          (if maximized?
          (if maximized?
            (svg/window-restore)
            (svg/window-restore)
            (svg/window-maximize))]
            (svg/window-maximize))]
 
 
         [:button.button.icon.close
         [:button.button.icon.close
          {:title (t :window/close)
          {:title (t :window/close)
-          :on-click close}
+          :on-click window-handler/close!}
          (svg/window-close)]])]))
          (svg/window-close)]])]))

+ 14 - 10
src/main/frontend/config.cljs

@@ -496,16 +496,20 @@
   "Resolve all relative links in custom.css to assets:// URL"
   "Resolve all relative links in custom.css to assets:// URL"
   ;; ../assets/xxx -> {assets|file}://{current-graph-root-path}/xxx
   ;; ../assets/xxx -> {assets|file}://{current-graph-root-path}/xxx
   [source]
   [source]
-  (let [protocol (and (string? source)
-                      (not (string/blank? source))
-                      (if (util/electron?) "assets://" "file://"))
-        ;; BUG: use "assets" as fake current directory
-        assets-link-fn (fn [_]
-                         (str (path/path-join protocol
-                                              (get-repo-dir (state/get-current-repo)) "assets") "/"))]
-    (when (not-empty source)
-      (string/replace source #"\.\./assets/"
-                      assets-link-fn))))
+  (when-not (string/blank? source)
+    (let [protocol (and (string? source)
+                        (not (string/blank? source))
+                        (if (util/electron?) "assets://" "file://"))
+          ;; BUG: use "assets" as fake current directory
+          assets-link-fn (fn [_]
+                           (let [graph-root (get-repo-dir (state/get-current-repo))
+                                 protocol (if (string/starts-with? graph-root "file:") "" protocol)
+                                 full-path (path/path-join protocol graph-root "assets")]
+                             (str (cond-> full-path
+                                          (mobile-util/native-platform?)
+                                          (mobile-util/convert-file-src))
+                                  "/")))]
+      (string/replace source #"\.\./assets/" assets-link-fn))))
 
 
 (defn get-current-repo-assets-root
 (defn get-current-repo-assets-root
   []
   []

+ 1 - 1
src/main/frontend/extensions/code.cljs

@@ -485,7 +485,7 @@
                  (when-not (:file? (first (:rum/args state)))
                  (when-not (:file? (first (:rum/args state)))
                    (let [code (nth (:rum/args state) 3)
                    (let [code (nth (:rum/args state) 3)
                          editor @(:editor-atom state)]
                          editor @(:editor-atom state)]
-                     (when (not= (.getValue editor) code)
+                     (when (and editor (not= (.getValue editor) code))
                        (.setValue editor code))))
                        (.setValue editor code))))
                  state)}
                  state)}
   [state _config id attr code _theme _options]
   [state _config id attr code _theme _options]

+ 18 - 15
src/main/frontend/extensions/pdf/core.cljs

@@ -886,21 +886,24 @@
      [hls-file])
      [hls-file])
 
 
     ;; cache highlights
     ;; cache highlights
-    (rum/use-effect!
-     (fn []
-       (when (= :completed (:status loader-state))
-         (p/catch
-          (when-not (:error hls-state)
-            (p/do!
-              (p/delay 100)
-              (pdf-assets/persist-hls-data$
-                pdf-current (:latest-hls hls-state) (:extra hls-state))))
-
-          ;; write hls file error
-          (fn [e]
-            (js/console.error "[write hls error]" e)))))
-
-     [(:latest-hls hls-state) (:extra hls-state)])
+    (let [persist-hls-data!
+          (rum/use-callback
+            (util/debounce
+              4000 (fn [latest-hls extra]
+                    (pdf-assets/persist-hls-data$
+                      pdf-current latest-hls extra))) [pdf-current])]
+      (rum/use-effect!
+        (fn []
+          (when (= :completed (:status loader-state))
+            (p/catch
+              (when-not (:error hls-state)
+                (p/do! (persist-hls-data! (:latest-hls hls-state) (:extra hls-state))))
+
+              ;; write hls file error
+              (fn [e]
+                (js/console.error "[write hls error]" e)))))
+
+        [(:latest-hls hls-state) (:extra hls-state)]))
 
 
     ;; load document
     ;; load document
     (rum/use-effect!
     (rum/use-effect!

+ 4 - 10
src/main/frontend/extensions/video/youtube.cljs

@@ -119,13 +119,13 @@ Remember: You can paste a raw YouTube url as embedded video on mobile."
 
 
 
 
 (defn parse-timestamp [timestamp]
 (defn parse-timestamp [timestamp]
-  (let [reg #"^(?:(\d+):)?([0-5]\d):([0-5]\d)$"
+  (let [reg #"^(?:(\d+):)?([0-5]?\d):([0-5]?\d)$"
         reg-number #"^\d+$"
         reg-number #"^\d+$"
         timestamp (str timestamp)
         timestamp (str timestamp)
         total-seconds (some-> (re-matches reg-number timestamp)
         total-seconds (some-> (re-matches reg-number timestamp)
                               util/safe-parse-int)
                               util/safe-parse-int)
         [_ hours minutes seconds] (re-matches reg timestamp)
         [_ hours minutes seconds] (re-matches reg timestamp)
-        [hours minutes seconds] (map util/safe-parse-int (remove nil? [hours minutes seconds]))]
+        [hours minutes seconds] (map #(if (nil? %) 0 (util/safe-parse-int %)) [hours minutes seconds])]
     (cond
     (cond
       total-seconds
       total-seconds
       total-seconds
       total-seconds
@@ -133,19 +133,13 @@ Remember: You can paste a raw YouTube url as embedded video on mobile."
       (and minutes seconds)
       (and minutes seconds)
       (+ (* 3600 hours) (* 60 minutes) seconds)
       (+ (* 3600 hours) (* 60 minutes) seconds)
 
 
-      minutes
-      (+ (* 3600 hours) (* 60 minutes))
-
-      hours
-      (* 3600 hours)
-
       :else
       :else
       nil)))
       nil)))
 
 
 (comment
 (comment
   ;; hh:mm:ss
   ;; hh:mm:ss
-  (re-matches #"^(?:(\d+):)?([0-5]\d):([0-5]\d)$" "123:22:23") ;; => ["123:22:23" "123" "22" "23"]
-  (re-matches #"^(?:(\d+):)?([0-5]\d):([0-5]\d)$" "30:23") ;; => ["30:23" nil "30" "23"]
+  (re-matches #"^(?:(\d+):)?([0-5]?\d):([0-5]?\d)$" "123:22:23") ;; => ["123:22:23" "123" "22" "23"]
+  (re-matches #"^(?:(\d+):)?([0-5]?\d):([0-5]?\d)$" "30:23") ;; => ["30:23" nil "30" "23"]
 
 
   (parse-timestamp "01:23") ;; => 83
   (parse-timestamp "01:23") ;; => 83
 
 

+ 1 - 1
src/main/frontend/handler/dnd.cljs

@@ -1,5 +1,5 @@
 (ns frontend.handler.dnd
 (ns frontend.handler.dnd
-  "Provides fns for drag n drop"
+  "Provides fns for drag and drop"
   (:require [frontend.handler.editor :as editor-handler]
   (:require [frontend.handler.editor :as editor-handler]
             [frontend.handler.property :as property-handler]
             [frontend.handler.property :as property-handler]
             [frontend.modules.outliner.core :as outliner-core]
             [frontend.modules.outliner.core :as outliner-core]

+ 5 - 2
src/main/frontend/handler/editor.cljs

@@ -2526,7 +2526,7 @@
             :down util/get-next-block-non-collapsed)
             :down util/get-next-block-non-collapsed)
         sibling-block (f (gdom/getElement (state/get-editing-block-dom-id)))
         sibling-block (f (gdom/getElement (state/get-editing-block-dom-id)))
         {:block/keys [uuid content format]} (state/get-edit-block)]
         {:block/keys [uuid content format]} (state/get-edit-block)]
-    (when sibling-block
+    (if sibling-block
       (when-let [sibling-block-id (dom/attr sibling-block "blockid")]
       (when-let [sibling-block-id (dom/attr sibling-block "blockid")]
         (let [value (state/get-edit-content)]
         (let [value (state/get-edit-content)]
           (when (not= (clean-content! repo format content)
           (when (not= (clean-content! repo format content)
@@ -2540,7 +2540,10 @@
                        (or (:pos move-opts)
                        (or (:pos move-opts)
                         [direction line-pos])
                         [direction line-pos])
                        new-id
                        new-id
-                       {:direction direction}))))))
+                       {:direction direction})))
+      (case direction
+        :up (cursor/move-cursor-to input 0)
+        :down (cursor/move-cursor-to-end input)))))
 
 
 (defn keydown-up-down-handler
 (defn keydown-up-down-handler
   [direction {:keys [_pos] :as move-opts}]
   [direction {:keys [_pos] :as move-opts}]

+ 2 - 11
src/main/frontend/handler/web/nfs.cljs

@@ -21,7 +21,6 @@
             [lambdaisland.glogi :as log]
             [lambdaisland.glogi :as log]
             [logseq.graph-parser.util :as gp-util]
             [logseq.graph-parser.util :as gp-util]
             [promesa.core :as p]
             [promesa.core :as p]
-            [logseq.common.path :as path]
             [frontend.db.listener :as db-listener]))
             [frontend.db.listener :as db-listener]))
 
 
 (defn remove-ignore-files
 (defn remove-ignore-files
@@ -91,18 +90,10 @@
 (defn- precheck-graph-dir
 (defn- precheck-graph-dir
   "Check graph dir, notify user if:
   "Check graph dir, notify user if:
 
 
-   - Grame dir name is `logseq`, the same as app, which might cause confusion
    - Graph dir contains a nested graph, which should be avoided
    - Graph dir contains a nested graph, which should be avoided
    - Over 10000 files found in graph dir, which might cause performance issues"
    - Over 10000 files found in graph dir, which might cause performance issues"
-  [dir files]
-  (when (= (string/lower-case (path/basename dir))
-           "logseq")
-    (state/pub-event!
-     [:notification/show {:content [:div "The folder name "
-                                    [:code "logseq"]
-                                    " is not suitable for a graph name. Please unlink this graph and choose a different name."]
-                          :status :warning
-                          :clear?  false}]))
+  [_dir files]
+  ;; disable this check for now
   (when (some #(string/ends-with? (:path %) "/logseq/config.edn") files)
   (when (some #(string/ends-with? (:path %) "/logseq/config.edn") files)
     (state/pub-event!
     (state/pub-event!
      [:notification/show {:content "It seems that you are trying to open a Logseq graph folder with nested graph. Please unlink this graph and choose a correct folder."
      [:notification/show {:content "It seems that you are trying to open a Logseq graph folder with nested graph. Please unlink this graph and choose a correct folder."

+ 2 - 2
src/main/frontend/handler/whiteboard.cljs

@@ -252,8 +252,8 @@
           point (-> (.getShapeById app source-shape)
           point (-> (.getShapeById app source-shape)
                     (.-bounds)
                     (.-bounds)
                     ((fn [bounds] (if bottom?
                     ((fn [bounds] (if bottom?
-                                    [(.-minX bounds) (+ 64 (.-maxY bounds))]
-                                    [(+ 64 (.-maxX bounds)) (.-minY bounds)]))))
+                                    [(.-minX ^js bounds) (+ 64 (.-maxY ^js bounds))]
+                                    [(+ 64 (.-maxX ^js bounds)) (.-minY ^js bounds)]))))
           shape (->logseq-portal-shape block-uuid point)]
           shape (->logseq-portal-shape block-uuid point)]
       (when (uuid? block-uuid) (editor-handler/set-blocks-id! [block-uuid]))
       (when (uuid? block-uuid) (editor-handler/set-blocks-id! [block-uuid]))
       (.createShapes api (clj->js shape))
       (.createShapes api (clj->js shape))

+ 19 - 0
src/main/frontend/handler/window.cljs

@@ -0,0 +1,19 @@
+(ns frontend.handler.window
+  "Window management ns"
+  (:require [electron.ipc :as ipc]))
+
+(defn minimize!
+  []
+  (ipc/ipc "window-minimize"))
+
+(defn toggle-maximized!
+  []
+  (ipc/ipc "window-toggle-maximized"))
+
+(defn close!
+  []
+  (ipc/ipc "window-close"))
+
+(defn toggle-fullscreen!
+  []
+  (ipc/ipc "window-toggle-fullscreen"))

+ 7 - 0
src/main/frontend/modules/shortcut/config.cljs

@@ -16,6 +16,7 @@
             [frontend.handler.export :as export-handler]
             [frontend.handler.export :as export-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
             [frontend.handler.plugin-config :as plugin-config-handler]
             [frontend.handler.plugin-config :as plugin-config-handler]
+            [frontend.handler.window :as window-handler]
             [frontend.modules.editor.undo-redo :as undo-redo]
             [frontend.modules.editor.undo-redo :as undo-redo]
             [frontend.dicts :as dicts]
             [frontend.dicts :as dicts]
             [frontend.modules.shortcut.before :as m]
             [frontend.modules.shortcut.before :as m]
@@ -513,6 +514,10 @@
                                              :inactive (not (util/electron?))
                                              :inactive (not (util/electron?))
                                              :fn       #(page-handler/copy-page-url)}
                                              :fn       #(page-handler/copy-page-url)}
 
 
+   :window/close                            {:binding  "mod+w"
+                                             :inactive (not (util/electron?))
+                                             :fn       window-handler/close!}
+
    :ui/toggle-wide-mode                     {:binding "t w"
    :ui/toggle-wide-mode                     {:binding "t w"
                                              :fn      ui-handler/toggle-wide-mode!}
                                              :fn      ui-handler/toggle-wide-mode!}
 
 
@@ -724,6 +729,7 @@
            :editor/open-file-in-directory
            :editor/open-file-in-directory
            :editor/copy-current-file
            :editor/copy-current-file
            :editor/copy-page-url
            :editor/copy-page-url
+           :window/close
            :editor/new-whiteboard
            :editor/new-whiteboard
            :ui/toggle-wide-mode
            :ui/toggle-wide-mode
            :ui/select-theme-color
            :ui/select-theme-color
@@ -902,6 +908,7 @@
      :editor/open-file-in-default-app
      :editor/open-file-in-default-app
      :editor/open-file-in-directory
      :editor/open-file-in-directory
      :editor/copy-page-url
      :editor/copy-page-url
+     :window/close
      :auto-complete/prev
      :auto-complete/prev
      :auto-complete/next
      :auto-complete/next
      :auto-complete/complete
      :auto-complete/complete

+ 22 - 18
src/main/frontend/ui.cljs

@@ -93,20 +93,24 @@
 (rum/defc ls-textarea
 (rum/defc ls-textarea
   < rum/reactive
   < rum/reactive
   {:did-mount (fn [state]
   {:did-mount (fn [state]
-                (let [^js el (rum/dom-node state)]
+                (let [^js el (rum/dom-node state)
+                      *mouse-point (volatile! nil)]
                   ;; Passing aria-label as a prop to TextareaAutosize removes the dash
                   ;; Passing aria-label as a prop to TextareaAutosize removes the dash
                   (.setAttribute el "aria-label" "editing block")
                   (.setAttribute el "aria-label" "editing block")
-                  (. el addEventListener "select"
-                     #(let [start (util/get-selection-start el)
-                            end (util/get-selection-end el)]
-                        (when (and start end)
-                          (when-let [e (and (not= start end)
-                                            {:caret (cursor/get-caret-pos el)
-                                             :start start :end end
-                                             :text  (. (.-value el) substring start end)
-                                             :point {:x (.-x %) :y (.-y %)}})]
-
-                            (plugin-handler/hook-plugin-editor :input-selection-end (bean/->js e)))))))
+                  (doto el
+                    (.addEventListener "select"
+                       #(let [start (util/get-selection-start el)
+                              end (util/get-selection-end el)]
+                          (when (and start end)
+                            (when-let [e (and (not= start end)
+                                              (let [caret-pos (cursor/get-caret-pos el)]
+                                                {:caret caret-pos
+                                                 :start start :end end
+                                                 :text  (. (.-value el) substring start end)
+                                                 :point (select-keys (or @*mouse-point caret-pos) [:x :y])}))]
+                              (plugin-handler/hook-plugin-editor :input-selection-end (bean/->js e))
+                              (vreset! *mouse-point nil)))))
+                    (.addEventListener "mouseup" #(vreset! *mouse-point {:x (.-x %) :y (.-y %)}))))
                 state)}
                 state)}
   [{:keys [on-change] :as props}]
   [{:keys [on-change] :as props}]
   (let [skip-composition? (state/sub :editor/action)
   (let [skip-composition? (state/sub :editor/action)
@@ -119,16 +123,16 @@
                                                 (on-change e))
                                                 (on-change e))
                              (state/set-editor-in-composition! true))))
                              (state/set-editor-in-composition! true))))
         props (assoc props
         props (assoc props
-                     :on-change (fn [e] (when-not (state/editor-in-composition?)
-                                          (on-change e)))
-                     :on-composition-start on-composition
-                     :on-composition-update on-composition
-                     :on-composition-end on-composition)]
+                :on-change (fn [e] (when-not (state/editor-in-composition?)
+                                     (on-change e)))
+                :on-composition-start on-composition
+                :on-composition-update on-composition
+                :on-composition-end on-composition)]
     (textarea props)))
     (textarea props)))
 
 
 (rum/defc dropdown-content-wrapper
 (rum/defc dropdown-content-wrapper
   < {:did-mount    (fn [state]
   < {:did-mount    (fn [state]
-                     (let [k    (inc (count (state/sub :modal/dropdowns)))
+                     (let [k (inc (count (state/sub :modal/dropdowns)))
                            args (:rum/args state)]
                            args (:rum/args state)]
                        (state/set-state! [:modal/dropdowns k] (second args))
                        (state/set-state! [:modal/dropdowns k] (second args))
                        (assoc state ::k k)))
                        (assoc state ::k k)))

+ 3 - 3
src/main/frontend/util.cljc

@@ -6,7 +6,7 @@
             ["/frontend/selection" :as selection]
             ["/frontend/selection" :as selection]
             ["/frontend/utils" :as utils]
             ["/frontend/utils" :as utils]
             ["@capacitor/status-bar" :refer [^js StatusBar Style]]
             ["@capacitor/status-bar" :refer [^js StatusBar Style]]
-            ["@hugotomazi/capacitor-navigation-bar" :refer [^js NavigationBar]]
+            ["@capgo/capacitor-navigation-bar" :refer [^js NavigationBar]]
             ["grapheme-splitter" :as GraphemeSplitter]
             ["grapheme-splitter" :as GraphemeSplitter]
             ["remove-accents" :as removeAccents]
             ["remove-accents" :as removeAccents]
             ["sanitize-filename" :as sanitizeFilename]
             ["sanitize-filename" :as sanitizeFilename]
@@ -215,7 +215,7 @@
      (p/do!
      (p/do!
       (.setStyle StatusBar (clj->js {:style (.-Light Style)}))
       (.setStyle StatusBar (clj->js {:style (.-Light Style)}))
       (when (mobile-util/native-android?)
       (when (mobile-util/native-android?)
-        (.setColor NavigationBar (clj->js {:color "#ffffff"}))
+        (.setNavigationBarColor NavigationBar (clj->js {:color "#ffffff"}))
         (.setBackgroundColor StatusBar (clj->js {:color "#ffffff"}))))))
         (.setBackgroundColor StatusBar (clj->js {:color "#ffffff"}))))))
 
 
 #?(:cljs
 #?(:cljs
@@ -224,7 +224,7 @@
      (p/do!
      (p/do!
       (.setStyle StatusBar (clj->js {:style (.-Dark Style)}))
       (.setStyle StatusBar (clj->js {:style (.-Dark Style)}))
       (when (mobile-util/native-android?)
       (when (mobile-util/native-android?)
-        (.setColor NavigationBar (clj->js {:color "#002b36"}))
+        (.setNavigationBarColor NavigationBar (clj->js {:color "#002b36"}))
         (.setBackgroundColor StatusBar (clj->js {:color "#002b36"}))))))
         (.setBackgroundColor StatusBar (clj->js {:color "#002b36"}))))))
 
 
 (defn find-first
 (defn find-first

+ 1 - 1
src/main/frontend/version.cljs

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

+ 5 - 1
src/resources/dicts/en.edn

@@ -353,6 +353,8 @@
  :settings-page/update-error-2 " Please check out the "
  :settings-page/update-error-2 " Please check out the "
  :settings-permission/start-granting "Grant"
  :settings-permission/start-granting "Grant"
 
 
+ :settings-page/auto-chmod "Automatically change file permissions"
+ :settings-page/auto-chmod-desc "Disable to allow editing by multiple users with permissions granted by group membership."
  :yes "Yes"
  :yes "Yes"
 
 
  :submit "Submit"
  :submit "Submit"
@@ -465,6 +467,7 @@
  :whiteboard/dashboard-card-edited "Edited "
  :whiteboard/dashboard-card-edited "Edited "
  :whiteboard/toggle-grid "Toggle grid"
  :whiteboard/toggle-grid "Toggle grid"
  :whiteboard/snap-to-grid "Snap to grid"
  :whiteboard/snap-to-grid "Snap to grid"
+ :whiteboard/toggle-pen-mode "Toggle pen mode"
  :flashcards/modal-welcome-title "Time to create a card!"
  :flashcards/modal-welcome-title "Time to create a card!"
  :flashcards/modal-welcome-desc-1 "You can add \"#card\" to any block to turn it into a card or trigger \"/cloze\" to add some clozes."
  :flashcards/modal-welcome-desc-1 "You can add \"#card\" to any block to turn it into a card or trigger \"/cloze\" to add some clozes."
  :flashcards/modal-welcome-desc-2 "You can "
  :flashcards/modal-welcome-desc-2 "You can "
@@ -828,4 +831,5 @@
   :dev/show-block-data             "(Dev) Show block data"
   :dev/show-block-data             "(Dev) Show block data"
   :dev/show-block-ast              "(Dev) Show block AST"
   :dev/show-block-ast              "(Dev) Show block AST"
   :dev/show-page-data              "(Dev) Show page data"
   :dev/show-page-data              "(Dev) Show page data"
-  :dev/show-page-ast               "(Dev) Show page AST"}}
+  :dev/show-page-ast               "(Dev) Show page AST"
+  :window/close                    "Close window"}}

+ 38 - 23
src/resources/dicts/es.edn

@@ -13,10 +13,10 @@
  :delete                                            "Eliminar"
  :delete                                            "Eliminar"
  :discourse-title                                   "¡Nuestro foro!"
  :discourse-title                                   "¡Nuestro foro!"
  :download                                          "Descargar"
  :download                                          "Descargar"
+ :export                                            "Exportar"
  :export-copied-to-clipboard                        "¡Copiado al portapapeles!"
  :export-copied-to-clipboard                        "¡Copiado al portapapeles!"
  :export-copy-to-clipboard                          "Copiar al portapapeles"
  :export-copy-to-clipboard                          "Copiar al portapapeles"
  :export-edn                                        "Exportar a EDN"
  :export-edn                                        "Exportar a EDN"
- :export                                            "Exportar"
  :export-graph                                      "Exportar grafo"
  :export-graph                                      "Exportar grafo"
  :export-json                                       "Exportar a JSON"
  :export-json                                       "Exportar a JSON"
  :export-markdown                                   "Exportar como Markdown estándar (sin propiedades de bloque)"
  :export-markdown                                   "Exportar como Markdown estándar (sin propiedades de bloque)"
@@ -53,23 +53,24 @@
  :parsing-files                                     "Analizando archivos"
  :parsing-files                                     "Analizando archivos"
  :plugins                                           "Extensiones"
  :plugins                                           "Extensiones"
  :port                                              "Puerto"
  :port                                              "Puerto"
+ :re-index                                          "Reindexar"
  :re-index-detail                                   "Reconstruir el grafo"
  :re-index-detail                                   "Reconstruir el grafo"
  :re-index-discard-unsaved-changes-warning          "Al reindexar se descartará el grafo actual y se procesarán nuevamente todos los archivos según como están actualmente almacenados en disco. Perderá los cambios no guardados y puede tardar un poco. ¿Continuar?"
  :re-index-discard-unsaved-changes-warning          "Al reindexar se descartará el grafo actual y se procesarán nuevamente todos los archivos según como están actualmente almacenados en disco. Perderá los cambios no guardados y puede tardar un poco. ¿Continuar?"
  :re-index-multiple-windows-warning                 "Debe cerrar las otras ventanas antes de reindexar este grafo."
  :re-index-multiple-windows-warning                 "Debe cerrar las otras ventanas antes de reindexar este grafo."
- :re-index                                          "Reindexar"
  :relaunch-confirm-to-work                          "Debe relanzar la aplicación para hacer que funcione. ¿Desea reiniciarla ahora?"
  :relaunch-confirm-to-work                          "Debe relanzar la aplicación para hacer que funcione. ¿Desea reiniciarla ahora?"
  :remove-background                                 "Eliminar el fondo"
  :remove-background                                 "Eliminar el fondo"
  :remove-heading                                    "Eliminar encabezado"
  :remove-heading                                    "Eliminar encabezado"
  :remove-orphaned-pages                             "¿Eliminar páginas huérfanas?"
  :remove-orphaned-pages                             "¿Eliminar páginas huérfanas?"
+ :reset                                             "Reiniciar"
  :save                                              "Guardar"
  :save                                              "Guardar"
  :search                                            "Buscar o Crear Página"
  :search                                            "Buscar o Crear Página"
- :settings-of-plugins                               "Opciones de Extensiones"
  :settings                                          "Opciones"
  :settings                                          "Opciones"
+ :settings-of-plugins                               "Opciones de Extensiones"
  :strikethrough                                     "Tachado"
  :strikethrough                                     "Tachado"
  :submit                                            "Enviar"
  :submit                                            "Enviar"
  :sync-from-local-changes-detected                  "Refrescar detecta y procesa los archivos modificados en su disco que difieren del contenido actual de la página en Logseq. ¿Continuar?"
  :sync-from-local-changes-detected                  "Refrescar detecta y procesa los archivos modificados en su disco que difieren del contenido actual de la página en Logseq. ¿Continuar?"
- :sync-from-local-files-detail                      "Importar cambios de los archivos locales"
  :sync-from-local-files                             "Refrescar"
  :sync-from-local-files                             "Refrescar"
+ :sync-from-local-files-detail                      "Importar cambios de los archivos locales"
  :themes                                            "Temas"
  :themes                                            "Temas"
  :toggle-theme                                      "Alternar tema"
  :toggle-theme                                      "Alternar tema"
  :type                                              "Tipo"
  :type                                              "Tipo"
@@ -151,8 +152,8 @@
  :command.editor/copy-text                          "Copiar selección como texto"
  :command.editor/copy-text                          "Copiar selección como texto"
  :command.editor/cut                                "Pegar"
  :command.editor/cut                                "Pegar"
  :command.editor/cycle-todo                         "Rotar estado TODO del elemento"
  :command.editor/cycle-todo                         "Rotar estado TODO del elemento"
- :command.editor/delete-selection                   "Eliminar bloques seleccionados"
  :command.editor/delete                             "Suprimir / Eliminar hacia delante"
  :command.editor/delete                             "Suprimir / Eliminar hacia delante"
+ :command.editor/delete-selection                   "Eliminar bloques seleccionados"
  :command.editor/down                               "Mover cursor abajo / Seleccionar abajo"
  :command.editor/down                               "Mover cursor abajo / Seleccionar abajo"
  :command.editor/end-of-block                       "Mover cursor al final del bloque"
  :command.editor/end-of-block                       "Mover cursor al final del bloque"
  :command.editor/escape-editing                     "Escapar de edición"
  :command.editor/escape-editing                     "Escapar de edición"
@@ -317,8 +318,8 @@
  :file-rn/need-action                               "Se sugieren acciones de cambio de nombre de archivo para que coincidan con el nuevo formato. Cuando se sincronicen los archivos renombrados se requiere volver a indexar en todos los dispositivos."
  :file-rn/need-action                               "Se sugieren acciones de cambio de nombre de archivo para que coincidan con el nuevo formato. Cuando se sincronicen los archivos renombrados se requiere volver a indexar en todos los dispositivos."
  :file-rn/no-action                                 "¡Bien hecho! No es necesario realizar más acciones."
  :file-rn/no-action                                 "¡Bien hecho! No es necesario realizar más acciones."
  :file-rn/optional-rename                           "Sugerencia: "
  :file-rn/optional-rename                           "Sugerencia: "
- :file-rn/or-select-actions-2                       ". Estas acciones no estarán disponibles una vez cierres este panel."
  :file-rn/or-select-actions                         " o cambie el nombre de los archivos a continuación individualmente, luego "
  :file-rn/or-select-actions                         " o cambie el nombre de los archivos a continuación individualmente, luego "
+ :file-rn/or-select-actions-2                       ". Estas acciones no estarán disponibles una vez cierres este panel."
  :file-rn/otherwise-breaking                        "O el título se convertirá"
  :file-rn/otherwise-breaking                        "O el título se convertirá"
  :file-rn/re-index                                  "Se recomienda encarecidamente volver a indexar después de cambiar el nombre de los archivos y en otros dispositivos después de la sincronización."
  :file-rn/re-index                                  "Se recomienda encarecidamente volver a indexar después de cambiar el nombre de los archivos y en otros dispositivos después de la sincronización."
  :file-rn/rename                                    "Renombrar \"{1}\" a \"{2}\""
  :file-rn/rename                                    "Renombrar \"{1}\" a \"{2}\""
@@ -326,6 +327,7 @@
  :file-rn/select-format                             "(Opción modo desarrollador, ¡peligroso!) Seccione el formato de nombre de archivo"
  :file-rn/select-format                             "(Opción modo desarrollador, ¡peligroso!) Seccione el formato de nombre de archivo"
  :file-rn/suggest-rename                            "Acción necesaria: "
  :file-rn/suggest-rename                            "Acción necesaria: "
  :file-rn/unreachable-title                         "¡Advertencia! El nombre de la página se convertirá en {1} en el formato de nombre de archivo actual, a no ser que la propiedad `title::` se establezca manualmente"
  :file-rn/unreachable-title                         "¡Advertencia! El nombre de la página se convertirá en {1} en el formato de nombre de archivo actual, a no ser que la propiedad `title::` se establezca manualmente"
+ :file-sync/connectivity-testing-failed             "Fallaron las pruebas de conexión de red. Consulte la configuración de su red. URLs de prueba: "
  :file-sync/graph-deleted                           "El gráfico remoto actual se ha eliminado"
  :file-sync/graph-deleted                           "El gráfico remoto actual se ha eliminado"
  :file-sync/other-user-graph                        "El gráfico local actual está unido al gráfico remoto de otro usuario, así que no se puede empezar a sincronizar"
  :file-sync/other-user-graph                        "El gráfico local actual está unido al gráfico remoto de otro usuario, así que no se puede empezar a sincronizar"
  :file-sync/rsapi-cannot-upload-err                 "Incapaz de comenzar la sincronización, comprueba si el tiempo local es correcto."
  :file-sync/rsapi-cannot-upload-err                 "Incapaz de comenzar la sincronización, comprueba si el tiempo local es correcto."
@@ -353,11 +355,11 @@
  :flashcards/modal-welcome-title                    "¡Hora de crear una tarjeta!"
  :flashcards/modal-welcome-title                    "¡Hora de crear una tarjeta!"
  :graph/all-graphs                                  "Todos los grafos"
  :graph/all-graphs                                  "Todos los grafos"
  :graph/local-graphs                                "Grafos locales:"
  :graph/local-graphs                                "Grafos locales:"
- :graph/persist-error                               "Falló la sincronización del estado interno."
  :graph/persist                                     "Logseq está sincronizando su estado interno, por favor espere unos segundos."
  :graph/persist                                     "Logseq está sincronizando su estado interno, por favor espere unos segundos."
+ :graph/persist-error                               "Falló la sincronización del estado interno."
  :graph/remote-graphs                               "Grafos remotos:"
  :graph/remote-graphs                               "Grafos remotos:"
- :graph/save-error                                  "Falló el guardado"
  :graph/save                                        "Guardando..."
  :graph/save                                        "Guardando..."
+ :graph/save-error                                  "Falló el guardado"
  :graph/save-success                                "Guardado satisfactoriamente"
  :graph/save-success                                "Guardado satisfactoriamente"
  :header/go-back                                    "Ir hacia atrás"
  :header/go-back                                    "Ir hacia atrás"
  :header/go-forward                                 "Ir haca adelante"
  :header/go-forward                                 "Ir haca adelante"
@@ -393,6 +395,18 @@
  :help/title-development                            "Desarrollo"
  :help/title-development                            "Desarrollo"
  :help/title-terms                                  "Términos"
  :help/title-terms                                  "Términos"
  :help/title-usage                                  "Uso"
  :help/title-usage                                  "Uso"
+ :keymap/all                                        "Todo"
+ :keymap/conflicts-for-label                        "Conflicto de combinación de teclas para"
+ :keymap/custom                                     "Personalizado"
+ :keymap/customize-for-label                        "Personalizar atajos"
+ :keymap/disabled                                   "Deshabilitado"
+ :keymap/keystroke-filter                           "Filtro de pulsación de teclas"
+ :keymap/keystroke-record-desc                      "Presione cualquier secuencia de teclas para filtrar atajos"
+ :keymap/keystroke-record-setup-label               "Presione cualquier secuencia de teclas para establecer un atajo"
+ :keymap/restore-to-default                         "Reiniciar a valor predeterminado del sistema"
+ :keymap/search                                     "Buscar"
+ :keymap/total                                      "Atajos de teclado totales"
+ :keymap/unset                                      "Sin asignar"
  :left-side-bar/create                              "Crear"
  :left-side-bar/create                              "Crear"
  :left-side-bar/journals                            "Diarios"
  :left-side-bar/journals                            "Diarios"
  :left-side-bar/nav-favorites                       "Favoritos"
  :left-side-bar/nav-favorites                       "Favoritos"
@@ -464,8 +478,8 @@
  :page/backlinks                                    "Vínculos de retroceso"
  :page/backlinks                                    "Vínculos de retroceso"
  :page/copy-page-url                                "Copiar URL de la página"
  :page/copy-page-url                                "Copiar URL de la página"
  :page/created-at                                   "Creada el"
  :page/created-at                                   "Creada el"
- :page/delete-confirmation                          "¿Está seguro que desea eliminar esta página y su archivo?"
  :page/delete                                       "Eliminar página"
  :page/delete                                       "Eliminar página"
+ :page/delete-confirmation                          "¿Está seguro que desea eliminar esta página y su archivo?"
  :page/earlier                                      "Anteriormente"
  :page/earlier                                      "Anteriormente"
  :page/illegal-page-name                            "¡Nombre de página ilegal!"
  :page/illegal-page-name                            "¡Nombre de página ilegal!"
  :page/logseq-is-having-a-problem                   "Logseq está teniendo un problema. Para intentar volver a un estado de trabajo, intenta los siguientes pasos seguros en orden:"
  :page/logseq-is-having-a-problem                   "Logseq está teniendo un problema. Para intentar volver a un estado de trabajo, intenta los siguientes pasos seguros en orden:"
@@ -477,8 +491,8 @@
  :page/page-already-exists                          "¡La página “{1}” ya existe!"
  :page/page-already-exists                          "¡La página “{1}” ya existe!"
  :page/show-journals                                "Mostrar diarios"
  :page/show-journals                                "Mostrar diarios"
  :page/show-whiteboards                             "Mostrar pizarras"
  :page/show-whiteboards                             "Mostrar pizarras"
- :page/slide-view-tip-go-fullscreen (fn [] [[:span.opacity-70 "Consejo: presiona "] [:code "f"] [:span.opacity-70 " para ir a pantalla completa"]])
  :page/slide-view                                   "Ver como diapositivas"
  :page/slide-view                                   "Ver como diapositivas"
+ :page/slide-view-tip-go-fullscreen (fn [] [[:span.opacity-70 "Consejo: presiona "] [:code "f"] [:span.opacity-70 " para ir a pantalla completa"]])
  :page/something-went-wrong                         "Algo malió sal"
  :page/something-went-wrong                         "Algo malió sal"
  :page/step                                         "Paso {1}"
  :page/step                                         "Paso {1}"
  :page/try                                          "Intentar"
  :page/try                                          "Intentar"
@@ -509,6 +523,7 @@
  :plugin/enabled                                    "Habilitado"
  :plugin/enabled                                    "Habilitado"
  :plugin/found-n-updates                            "Se encontraron {1} actualizaciones"
  :plugin/found-n-updates                            "Se encontraron {1} actualizaciones"
  :plugin/found-updates                              "Nuevas actualizaciones"
  :plugin/found-updates                              "Nuevas actualizaciones"
+ :plugin/install                                    "Instalar"
  :plugin/installed                                  "Instalado"
  :plugin/installed                                  "Instalado"
  :plugin/installed-plugin                           "Extensión instalada: {1}"
  :plugin/installed-plugin                           "Extensión instalada: {1}"
  :plugin.install-from-file/menu-title               "Instalar desde plugins.edn"
  :plugin.install-from-file/menu-title               "Instalar desde plugins.edn"
@@ -516,7 +531,6 @@
  :plugin.install-from-file/success                  "¡Todas las extensiones fueron instaladas!"
  :plugin.install-from-file/success                  "¡Todas las extensiones fueron instaladas!"
  :plugin.install-from-file/title                    "Instalar extensiones desde  plugins.edn"
  :plugin.install-from-file/title                    "Instalar extensiones desde  plugins.edn"
  :plugin/installing                                 "Instalando"
  :plugin/installing                                 "Instalando"
- :plugin/install                                    "Instalar"
  :plugin/list-of-updates                            "Actualizaciones de extensiones: "
  :plugin/list-of-updates                            "Actualizaciones de extensiones: "
  :plugin/load-unpacked                              "Cargar extensión desempaquetada"
  :plugin/load-unpacked                              "Cargar extensión desempaquetada"
  :plugin/marketplace                                "Tienda"
  :plugin/marketplace                                "Tienda"
@@ -557,14 +571,14 @@
  :right-side-bar/history-undos                      "Deshacer"
  :right-side-bar/history-undos                      "Deshacer"
  :right-side-bar/new-page                           "Nueva página"
  :right-side-bar/new-page                           "Nueva página"
  :right-side-bar/page-graph                         "Grafo de página"
  :right-side-bar/page-graph                         "Grafo de página"
+ :right-side-bar/pane-close                         "Cerrar"
  :right-side-bar/pane-close-all                     "Cerrar todo"
  :right-side-bar/pane-close-all                     "Cerrar todo"
  :right-side-bar/pane-close-others                  "Cerrar otros"
  :right-side-bar/pane-close-others                  "Cerrar otros"
- :right-side-bar/pane-close                         "Cerrar"
- :right-side-bar/pane-collapse-all                  "Colapsar todo"
  :right-side-bar/pane-collapse                      "Colapsar"
  :right-side-bar/pane-collapse                      "Colapsar"
+ :right-side-bar/pane-collapse-all                  "Colapsar todo"
  :right-side-bar/pane-collapse-others               "Colapsar otros"
  :right-side-bar/pane-collapse-others               "Colapsar otros"
- :right-side-bar/pane-expand-all                    "Expandir todo"
  :right-side-bar/pane-expand                        "Expandir"
  :right-side-bar/pane-expand                        "Expandir"
+ :right-side-bar/pane-expand-all                    "Expandir todo"
  :right-side-bar/pane-more                          "Más"
  :right-side-bar/pane-more                          "Más"
  :right-side-bar/pane-open-as-page                  "Abrir como página"
  :right-side-bar/pane-open-as-page                  "Abrir como página"
  :right-side-bar/separator                          "Right sidebar resize handler "
  :right-side-bar/separator                          "Right sidebar resize handler "
@@ -600,9 +614,9 @@
  :settings-page/changelog                           "¿Qué hay de nuevo?"
  :settings-page/changelog                           "¿Qué hay de nuevo?"
  :settings-page/check-for-updates                   "Comprobar actualizaciones"
  :settings-page/check-for-updates                   "Comprobar actualizaciones"
  :settings-page/checking                            "Comprobando ..."
  :settings-page/checking                            "Comprobando ..."
+ :settings-page/clear                               "Limpiar"
  :settings-page/clear-cache                         "Limpiar caché"
  :settings-page/clear-cache                         "Limpiar caché"
  :settings-page/clear-cache-warning                 "Limpiar la caché va a desechar los grafos abiertos. Vas a perder los cambios no guardados."
  :settings-page/clear-cache-warning                 "Limpiar la caché va a desechar los grafos abiertos. Vas a perder los cambios no guardados."
- :settings-page/clear                               "Limpiar"
  :settings-page/current-version                     "Versión actual"
  :settings-page/current-version                     "Versión actual"
  :settings-page/custom-configuration                "Configuración personalizada"
  :settings-page/custom-configuration                "Configuración personalizada"
  :settings-page/custom-date-format                  "Formato de fecha preferido"
  :settings-page/custom-date-format                  "Formato de fecha preferido"
@@ -610,10 +624,10 @@
  :settings-page/custom-date-format-warning          "¡Se requiere reindexar! ¡Las referencias existentes del diario podrían estar rotas!"
  :settings-page/custom-date-format-warning          "¡Se requiere reindexar! ¡Las referencias existentes del diario podrían estar rotas!"
  :settings-page/custom-global-configuration         "Configuración global personalizada"
  :settings-page/custom-global-configuration         "Configuración global personalizada"
  :settings-page/custom-theme                        "Tema personalizado"
  :settings-page/custom-theme                        "Tema personalizado"
- :settings-page/developer-mode-desc                 "El modo desarrollador permite a los colaboradores y desarrolladores de extensiones probar sus integraciones con Logseq más eficientemente."
  :settings-page/developer-mode                      "Modo desarrollador"
  :settings-page/developer-mode                      "Modo desarrollador"
- :settings-page/disable-sentry-desc                 " Logseq nunca va a recolectar tu base de datos de grafos local o vender tus datos."
+ :settings-page/developer-mode-desc                 "El modo desarrollador permite a los colaboradores y desarrolladores de extensiones probar sus integraciones con Logseq más eficientemente."
  :settings-page/disable-sentry                      "Enviar datos de uso y diagnósticos a Logseq"
  :settings-page/disable-sentry                      "Enviar datos de uso y diagnósticos a Logseq"
+ :settings-page/disable-sentry-desc                 " Logseq nunca va a recolectar tu base de datos de grafos local o vender tus datos."
  :settings-page/edit-config-edn                     "Editar config.edn (para este repositorio)"
  :settings-page/edit-config-edn                     "Editar config.edn (para este repositorio)"
  :settings-page/edit-custom-css                     "Editar custom.css"
  :settings-page/edit-custom-css                     "Editar custom.css"
  :settings-page/edit-export-css                     "Editar export.css"
  :settings-page/edit-export-css                     "Editar export.css"
@@ -645,26 +659,27 @@
  :settings-page/preferred-outdenting                "Disminución lógica de sangría"
  :settings-page/preferred-outdenting                "Disminución lógica de sangría"
  :settings-page/preferred-outdenting-tip            "El lado izquierdo muestra  sangría con la configuración por defecto, y el derecho muestra con sangría lógica habilitada"
  :settings-page/preferred-outdenting-tip            "El lado izquierdo muestra  sangría con la configuración por defecto, y el derecho muestra con sangría lógica habilitada"
  :settings-page/preferred-outdenting-tip-more       "→ Aprende más"
  :settings-page/preferred-outdenting-tip-more       "→ Aprende más"
- :settings-page/preferred-pasting-file-hint         "Cuando está habilitado, al pegar una imagen de internet la imagen será descargada e insertada. Cuando está deshabilitado, el enlace a la imagen será pegado."
  :settings-page/preferred-pasting-file              "Preferir pegar archivo"
  :settings-page/preferred-pasting-file              "Preferir pegar archivo"
+ :settings-page/preferred-pasting-file-hint         "Cuando está habilitado, al pegar una imagen de internet la imagen será descargada e insertada. Cuando está deshabilitado, el enlace a la imagen será pegado."
  :settings-page/preferred-workflow                  "Flujo de trabajo preferido"
  :settings-page/preferred-workflow                  "Flujo de trabajo preferido"
  :settings-page/revision                            "Revisión: "
  :settings-page/revision                            "Revisión: "
  :settings-page/show-brackets                       "Mostrar corchetes"
  :settings-page/show-brackets                       "Mostrar corchetes"
  :settings-page/show-full-blocks                    "Mostrar todas las líneas de una referencia a bloque"
  :settings-page/show-full-blocks                    "Mostrar todas las líneas de una referencia a bloque"
  :settings-page/spell-checker                       "Corrector ortográfico"
  :settings-page/spell-checker                       "Corrector ortográfico"
+ :settings-page/sync                                "Sincronizar"
  :settings-page/sync-desc-1                         "Clic"
  :settings-page/sync-desc-1                         "Clic"
  :settings-page/sync-desc-2                         "aquí"
  :settings-page/sync-desc-2                         "aquí"
  :settings-page/sync-desc-3                         "por instrucciones de cómo configurar y usar Sync."
  :settings-page/sync-desc-3                         "por instrucciones de cómo configurar y usar Sync."
- :settings-page/sync-diff-merge-desc                "Unir actualizaciones locales con archivos remotos automáticamente cuando ocurre un conflicto, en lugar de sobreescribir los archivos remotos"
  :settings-page/sync-diff-merge                     "Habilitar unión inteligente al sincronizar"
  :settings-page/sync-diff-merge                     "Habilitar unión inteligente al sincronizar"
+ :settings-page/sync-diff-merge-desc                "Unir actualizaciones locales con archivos remotos automáticamente cuando ocurre un conflicto, en lugar de sobreescribir los archivos remotos"
  :settings-page/sync-diff-merge-warn                "La capacidad de unión inteligente solo se activa en un cliente después de la primera sincronización exitosa con el servidor remoto en el grafo en la nueva versión de LogSeq. Habilita esto en todos los dispositivos para alcanzar la mejor experiencia."
  :settings-page/sync-diff-merge-warn                "La capacidad de unión inteligente solo se activa en un cliente después de la primera sincronización exitosa con el servidor remoto en el grafo en la nueva versión de LogSeq. Habilita esto en todos los dispositivos para alcanzar la mejor experiencia."
- :settings-page/sync                                "Sincronizar"
  :settings-page/tab-account                         "Cuenta"
  :settings-page/tab-account                         "Cuenta"
  :settings-page/tab-advanced                        "Avanzado"
  :settings-page/tab-advanced                        "Avanzado"
  :settings-page/tab-assets                          "Recursos"
  :settings-page/tab-assets                          "Recursos"
  :settings-page/tab-editor                          "Editor"
  :settings-page/tab-editor                          "Editor"
  :settings-page/tab-features                        "Características"
  :settings-page/tab-features                        "Características"
  :settings-page/tab-general                         "General"
  :settings-page/tab-general                         "General"
+ :settings-page/tab-keymap                          "Mapa de teclado"
  :settings-page/tab-version-control                 "Control de versiones"
  :settings-page/tab-version-control                 "Control de versiones"
  :settings-page/theme-dark                          "oscuro"
  :settings-page/theme-dark                          "oscuro"
  :settings-page/theme-light                         "claro"
  :settings-page/theme-light                         "claro"
@@ -734,8 +749,8 @@
  :whiteboard/medium                                 "Medio"
  :whiteboard/medium                                 "Medio"
  :whiteboard/move-to-back                           "Mover al fondo"
  :whiteboard/move-to-back                           "Mover al fondo"
  :whiteboard/move-to-front                          "Mover al frente"
  :whiteboard/move-to-front                          "Mover al frente"
- :whiteboard/new-block-no-colon                     "Nuevo bloque"
  :whiteboard/new-block                              "Nuevo bloque:"
  :whiteboard/new-block                              "Nuevo bloque:"
+ :whiteboard/new-block-no-colon                     "Nuevo bloque"
  :whiteboard/new-page                               "Nueva página:"
  :whiteboard/new-page                               "Nueva página:"
  :whiteboard/new-whiteboard                         "Nueva pizarra"
  :whiteboard/new-whiteboard                         "Nueva pizarra"
  :whiteboard/opacity                                "Opacidad"
  :whiteboard/opacity                                "Opacidad"
@@ -746,8 +761,8 @@
  :whiteboard/open-youtube-url                       "Abrir url de YouTube"
  :whiteboard/open-youtube-url                       "Abrir url de YouTube"
  :whiteboard/pack-into-rectangle                    "Empacar en un rectángulo"
  :whiteboard/pack-into-rectangle                    "Empacar en un rectángulo"
  :whiteboard/pan                                    "Mover"
  :whiteboard/pan                                    "Mover"
- :whiteboard/paste-as-link                          "Pegar como enlace"
  :whiteboard/paste                                  "Pegar"
  :whiteboard/paste                                  "Pegar"
+ :whiteboard/paste-as-link                          "Pegar como enlace"
  :whiteboard/rectangle                              "Recargar"
  :whiteboard/rectangle                              "Recargar"
  :whiteboard/redo                                   "Rehacer"
  :whiteboard/redo                                   "Rehacer"
  :whiteboard/references                             "Referencias"
  :whiteboard/references                             "Referencias"
@@ -756,9 +771,9 @@
  :whiteboard/scale-level                            "Escalar nivel"
  :whiteboard/scale-level                            "Escalar nivel"
  :whiteboard/search-only-blocks                     "Buscar solo bloques"
  :whiteboard/search-only-blocks                     "Buscar solo bloques"
  :whiteboard/search-only-pages                      "Buscar solo páginas"
  :whiteboard/search-only-pages                      "Buscar solo páginas"
+ :whiteboard/select                                 "Seleccionar"
  :whiteboard/select-all                             "Seleccionar todo"
  :whiteboard/select-all                             "Seleccionar todo"
  :whiteboard/select-custom-color                    "Seleccionar color personalizado"
  :whiteboard/select-custom-color                    "Seleccionar color personalizado"
- :whiteboard/select                                 "Seleccionar"
  :whiteboard/shape                                  "Forma"
  :whiteboard/shape                                  "Forma"
  :whiteboard/shape-quick-links                      "Enlaces rápidos de forma"
  :whiteboard/shape-quick-links                      "Enlaces rápidos de forma"
  :whiteboard/small                                  "Pequeño"
  :whiteboard/small                                  "Pequeño"

+ 29 - 1
src/resources/dicts/tr.edn

@@ -148,6 +148,16 @@
  :right-side-bar/show-journals "Günlükleri Göster"
  :right-side-bar/show-journals "Günlükleri Göster"
  :right-side-bar/separator "Sağ kenar çubuğu yeniden boyutlandırma işleyicisi"
  :right-side-bar/separator "Sağ kenar çubuğu yeniden boyutlandırma işleyicisi"
  :right-side-bar/toggle-right-sidebar "Sağ kenar çubuğunu aç/kapat"
  :right-side-bar/toggle-right-sidebar "Sağ kenar çubuğunu aç/kapat"
+ :right-side-bar/pane-close "Kapat"
+ :right-side-bar/pane-close-others "Diğerlerini kapat"
+ :right-side-bar/pane-close-all "Tümünü kapat"
+ :right-side-bar/pane-collapse "Daralt"
+ :right-side-bar/pane-collapse-others "Diğerlerini daralt"
+ :right-side-bar/pane-collapse-all "Tümünü daralt"
+ :right-side-bar/pane-expand "Genişlet"
+ :right-side-bar/pane-expand-all "Tümünü genişlet"
+ :right-side-bar/pane-open-as-page "Sayfa olarak aç"
+ :right-side-bar/pane-more "Diğer"
  :left-side-bar/switch "Geçiş yap:"
  :left-side-bar/switch "Geçiş yap:"
  :left-side-bar/journals "Günlük"
  :left-side-bar/journals "Günlük"
  :left-side-bar/create "Oluştur"
  :left-side-bar/create "Oluştur"
@@ -307,6 +317,7 @@
  :settings-page/current-version "Geçerli sürüm"
  :settings-page/current-version "Geçerli sürüm"
  :settings-page/tab-general "Genel"
  :settings-page/tab-general "Genel"
  :settings-page/tab-editor "Düzenleyici"
  :settings-page/tab-editor "Düzenleyici"
+ :settings-page/tab-keymap "Tuş haritası"
  :settings-page/tab-version-control "Sürüm denetimi"
  :settings-page/tab-version-control "Sürüm denetimi"
  :settings-page/tab-account "Hesap"
  :settings-page/tab-account "Hesap"
  :settings-page/tab-advanced "Gelişmiş"
  :settings-page/tab-advanced "Gelişmiş"
@@ -337,6 +348,8 @@
  :settings-page/update-available "Yeni sürüm bulundu: "
  :settings-page/update-available "Yeni sürüm bulundu: "
  :settings-page/update-error-1 "⚠️ Ne yazık ki bir sorun oluştu!"
  :settings-page/update-error-1 "⚠️ Ne yazık ki bir sorun oluştu!"
  :settings-page/update-error-2 " Lütfen bu bağlantıyı denetleyin: "
  :settings-page/update-error-2 " Lütfen bu bağlantıyı denetleyin: "
+ :settings-permission/start-granting "İzin ver"
+
  :yes "Evet"
  :yes "Evet"
 
 
  :submit "Onayla"
  :submit "Onayla"
@@ -344,6 +357,7 @@
  :close "Kapat"
  :close "Kapat"
  :delete "Sil"
  :delete "Sil"
  :save "Kaydet"
  :save "Kaydet"
+ :reset "Sıfırla"
  :type "Tür"
  :type "Tür"
  :host "Ana Bilgisayar"
  :host "Ana Bilgisayar"
  :port "Bağlantı Noktası"
  :port "Bağlantı Noktası"
@@ -611,6 +625,7 @@
  :file-sync/other-user-graph "Geçerli yerel graf, diğer kullanıcının uzak grafına bağlıdır. Bu yüzden eşitleme başlatılamıyor."
  :file-sync/other-user-graph "Geçerli yerel graf, diğer kullanıcının uzak grafına bağlıdır. Bu yüzden eşitleme başlatılamıyor."
  :file-sync/graph-deleted "Geçerli uzak graf silindi"
  :file-sync/graph-deleted "Geçerli uzak graf silindi"
  :file-sync/rsapi-cannot-upload-err "Eşitleme başlatılamıyor, lütfen yerel saatin doğru olup olmadığını kontrol edin."
  :file-sync/rsapi-cannot-upload-err "Eşitleme başlatılamıyor, lütfen yerel saatin doğru olup olmadığını kontrol edin."
+ :file-sync/connectivity-testing-failed "Ağ bağlantısı testi başarısız oldu. Lütfen ağ ayarlarınızı kontrol edin. Test URL'si: "
 
 
  :notification/clear-all "Tümünü temizle"
  :notification/clear-all "Tümünü temizle"
 
 
@@ -621,9 +636,22 @@
  :shortcut.category/block-command-editing "Blok düzenleme komutuları"
  :shortcut.category/block-command-editing "Blok düzenleme komutuları"
  :shortcut.category/block-selection "Blok seçimi (seçimden çıkmak için Esc tuşuna basın)"
  :shortcut.category/block-selection "Blok seçimi (seçimden çıkmak için Esc tuşuna basın)"
  :shortcut.category/toggle "Aç/Kapat"
  :shortcut.category/toggle "Aç/Kapat"
- :shortcut.category/whiteboard "Beyaz tahta"
  :shortcut.category/others "Diğer"
  :shortcut.category/others "Diğer"
  :shortcut.category/plugins "Eklentiler"
  :shortcut.category/plugins "Eklentiler"
+ :shortcut.category/whiteboard "Beyaz tahta"
+
+ :keymap/all "Tümü"
+ :keymap/disabled "Devre dışı"
+ :keymap/unset "Ayarlanmadı"
+ :keymap/custom "Özel"
+ :keymap/search "Ara"
+ :keymap/total "Toplam kısayol sayısı"
+ :keymap/keystroke-filter "Tuş filtresi"
+ :keymap/keystroke-record-desc "Kısayolları filtrelemek için herhangi bir tuş dizisine basın"
+ :keymap/keystroke-record-setup-label "Kısayolu ayarlamak için herhangi bir tuş dizisine basın"
+ :keymap/restore-to-default "Sistem varsayılanına geri yükle"
+ :keymap/customize-for-label "Kısayolları özelleştir"
+ :keymap/conflicts-for-label "Tuş haritası çakışması:"
  :window/minimize "Simge durumuna küçült"
  :window/minimize "Simge durumuna küçült"
  :window/maximize "Ekranı kapla"
  :window/maximize "Ekranı kapla"
  :window/restore "Pencere durumuna dön"
  :window/restore "Pencere durumuna dön"

+ 29 - 5
static/yarn.lock

@@ -757,6 +757,13 @@ agent-base@6, agent-base@^6.0.2:
   dependencies:
   dependencies:
     debug "4"
     debug "4"
 
 
+agent-base@^7.0.2:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434"
+  integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==
+  dependencies:
+    debug "^4.3.4"
+
 agentkeepalive@^4.2.1:
 agentkeepalive@^4.2.1:
   version "4.2.1"
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717"
   resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717"
@@ -2840,12 +2847,12 @@ http2-wrapper@^1.0.0-beta.5.2:
     quick-lru "^5.1.1"
     quick-lru "^5.1.1"
     resolve-alpn "^1.0.0"
     resolve-alpn "^1.0.0"
 
 
-https-proxy-agent@5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
-  integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
+https-proxy-agent@7.0.2:
+  version "7.0.2"
+  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b"
+  integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==
   dependencies:
   dependencies:
-    agent-base "6"
+    agent-base "^7.0.2"
     debug "4"
     debug "4"
 
 
 https-proxy-agent@^5.0.0:
 https-proxy-agent@^5.0.0:
@@ -4553,6 +4560,15 @@ smart-buffer@^4.0.2, smart-buffer@^4.2.0:
   resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
   resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
   integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
   integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
 
 
[email protected]:
+  version "8.0.2"
+  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad"
+  integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==
+  dependencies:
+    agent-base "^7.0.2"
+    debug "^4.3.4"
+    socks "^2.7.1"
+
 socks-proxy-agent@^7.0.0:
 socks-proxy-agent@^7.0.0:
   version "7.0.0"
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6"
   resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6"
@@ -4570,6 +4586,14 @@ socks@^2.6.2:
     ip "^2.0.0"
     ip "^2.0.0"
     smart-buffer "^4.2.0"
     smart-buffer "^4.2.0"
 
 
+socks@^2.7.1:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55"
+  integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==
+  dependencies:
+    ip "^2.0.0"
+    smart-buffer "^4.2.0"
+
 sonic-boom@^3.1.0:
 sonic-boom@^3.1.0:
   version "3.2.1"
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.1.tgz#972ceab831b5840a08a002fa95a672008bda1c38"
   resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.1.tgz#972ceab831b5840a08a002fa95a672008bda1c38"

+ 21 - 3
tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx

@@ -41,10 +41,14 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
     app.api.toggleSnapToGrid()
     app.api.toggleSnapToGrid()
   }, [app])
   }, [app])
 
 
+  const togglePenMode = React.useCallback(() => {
+    app.api.togglePenMode()
+  }, [app])
+
   return (
   return (
     <div className="tl-action-bar" data-html2canvas-ignore="true">
     <div className="tl-action-bar" data-html2canvas-ignore="true">
       {!app.readOnly && (
       {!app.readOnly && (
-        <div className="tl-toolbar tl-history-bar">
+        <div className="tl-toolbar tl-history-bar mr-2 mb-2">
           <Button tooltip={t('whiteboard/undo')} onClick={undo}>
           <Button tooltip={t('whiteboard/undo')} onClick={undo}>
             <TablerIcon name="arrow-back-up" />
             <TablerIcon name="arrow-back-up" />
           </Button>
           </Button>
@@ -54,7 +58,7 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
         </div>
         </div>
       )}
       )}
 
 
-      <div className={`tl-toolbar tl-zoom-bar ${app.readOnly ? '' : 'ml-4'}`}>
+      <div className={'tl-toolbar tl-zoom-bar mr-2 mb-2'}>
         <Button tooltip={t('whiteboard/zoom-in')} onClick={zoomIn} id="tl-zoom-in">
         <Button tooltip={t('whiteboard/zoom-in')} onClick={zoomIn} id="tl-zoom-in">
           <TablerIcon name="plus" />
           <TablerIcon name="plus" />
         </Button>
         </Button>
@@ -65,7 +69,7 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
         <ZoomMenu />
         <ZoomMenu />
       </div>
       </div>
 
 
-      <div className={'tl-toolbar tl-grid-bar ml-4'}>
+      <div className={'tl-toolbar tl-grid-bar mr-2 mb-2'}>
         <ToggleInput
         <ToggleInput
             tooltip={t('whiteboard/toggle-grid')}
             tooltip={t('whiteboard/toggle-grid')}
             className="tl-button"
             className="tl-button"
@@ -88,6 +92,20 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
           </ToggleInput>
           </ToggleInput>
         )}
         )}
       </div>
       </div>
+
+      {!app.readOnly && (
+        <div className="tl-toolbar tl-pen-mode-bar mb-2">
+          <ToggleInput
+            tooltip={t('whiteboard/toggle-pen-mode')}
+            className="tl-button"
+            pressed={app.settings.penMode}
+            id="tl-toggle-pen-mode"
+            onPressedChange={togglePenMode}
+          >
+          <TablerIcon name={app.settings.penMode ? "pencil" : "pencil-off"} />
+        </ToggleInput>
+        </div>
+      )}
     </div>
     </div>
   )
   )
 })
 })

+ 1 - 1
tldraw/apps/tldraw-logseq/src/styles.css

@@ -166,7 +166,7 @@ html[data-theme='light'] {
 }
 }
 
 
 .tl-action-bar {
 .tl-action-bar {
-  @apply absolute bottom-0 flex items-center border-0 left-10 bottom-10;
+  @apply absolute flex items-center border-0 left-10 bottom-8 flex-wrap-reverse pr-12;
 
 
   z-index: 100000;
   z-index: 100000;
   user-select: none;
   user-select: none;

+ 7 - 0
tldraw/packages/core/src/lib/TLApi/TLApi.ts

@@ -178,6 +178,13 @@ export class TLApi<S extends TLShape = TLShape, K extends TLEventMap = TLEventMa
     return this
     return this
   }
   }
 
 
+
+  togglePenMode = (): this => {
+    const { settings } = this.app
+    settings.update({ penMode: !settings.penMode })
+    return this
+  }
+
   setColor = (color: string): this => {
   setColor = (color: string): this => {
     const { settings } = this.app
     const { settings } = this.app
 
 

+ 2 - 0
tldraw/packages/core/src/lib/TLSettings.ts

@@ -4,6 +4,7 @@ import { observable, makeObservable, action } from 'mobx'
 export interface TLSettingsProps {
 export interface TLSettingsProps {
   mode: 'light' | 'dark'
   mode: 'light' | 'dark'
   showGrid: boolean
   showGrid: boolean
+  penMode: boolean
   snapToGrid: boolean
   snapToGrid: boolean
   color: string
   color: string
   scaleLevel: string
   scaleLevel: string
@@ -17,6 +18,7 @@ export class TLSettings implements TLSettingsProps {
   @observable mode: 'dark' | 'light' = 'light'
   @observable mode: 'dark' | 'light' = 'light'
   @observable showGrid = true
   @observable showGrid = true
   @observable snapToGrid = true
   @observable snapToGrid = true
+  @observable penMode = false
   @observable scaleLevel = 'md'
   @observable scaleLevel = 'md'
   @observable color = ''
   @observable color = ''
 
 

+ 1 - 0
tldraw/packages/react/src/components/AppCanvas.tsx

@@ -27,6 +27,7 @@ export const AppCanvas = observer(function InnerApp<S extends TLReactShape>(
       shapes={app.shapes} // TODO: use shapes in viewport later?
       shapes={app.shapes} // TODO: use shapes in viewport later?
       assets={app.assets}
       assets={app.assets}
       showGrid={app.settings.showGrid}
       showGrid={app.settings.showGrid}
+      penMode={app.settings.penMode}
       showSelection={app.showSelection}
       showSelection={app.showSelection}
       showSelectionRotation={app.showSelectionRotation}
       showSelectionRotation={app.showSelectionRotation}
       showResizeHandles={app.showResizeHandles}
       showResizeHandles={app.showResizeHandles}

+ 1 - 0
tldraw/packages/react/src/components/Canvas/Canvas.tsx

@@ -58,6 +58,7 @@ export interface TLCanvasProps<S extends TLReactShape> {
   cursorRotation: number
   cursorRotation: number
   selectionRotation: number
   selectionRotation: number
   onEditingEnd: () => void
   onEditingEnd: () => void
+  penMode: boolean
   showGrid: boolean
   showGrid: boolean
   showSelection: boolean
   showSelection: boolean
   showHandles: boolean
   showHandles: boolean

+ 20 - 0
tldraw/packages/react/src/hooks/useCanvasEvents.ts

@@ -13,11 +13,19 @@ export function useCanvasEvents() {
 
 
   const events = React.useMemo(() => {
   const events = React.useMemo(() => {
     const onPointerMove: TLReactCustomEvents['pointer'] = e => {
     const onPointerMove: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       callbacks.onPointerMove?.({ type: TLTargetType.Canvas, order }, e)
       callbacks.onPointerMove?.({ type: TLTargetType.Canvas, order }, e)
     }
     }
 
 
     const onPointerDown: TLReactCustomEvents['pointer'] = e => {
     const onPointerDown: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
       if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
 
 
@@ -41,17 +49,29 @@ export function useCanvasEvents() {
     }
     }
 
 
     const onPointerUp: TLReactCustomEvents['pointer'] = e => {
     const onPointerUp: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
       if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
       callbacks.onPointerUp?.({ type: TLTargetType.Canvas, order }, e)
       callbacks.onPointerUp?.({ type: TLTargetType.Canvas, order }, e)
     }
     }
 
 
     const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
     const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       callbacks.onPointerEnter?.({ type: TLTargetType.Canvas, order }, e)
       callbacks.onPointerEnter?.({ type: TLTargetType.Canvas, order }, e)
     }
     }
 
 
     const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
     const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       callbacks.onPointerLeave?.({ type: TLTargetType.Canvas, order }, e)
       callbacks.onPointerLeave?.({ type: TLTargetType.Canvas, order }, e)
     }
     }

+ 22 - 0
tldraw/packages/react/src/hooks/useShapeEvents.ts

@@ -1,23 +1,33 @@
 import * as React from 'react'
 import * as React from 'react'
 import { TLTargetType } from '@tldraw/core'
 import { TLTargetType } from '@tldraw/core'
+import { useApp } from './useApp'
 import { useRendererContext } from '.'
 import { useRendererContext } from '.'
 import { DOUBLE_CLICK_DURATION } from '../constants'
 import { DOUBLE_CLICK_DURATION } from '../constants'
 import type { TLReactShape } from '../lib'
 import type { TLReactShape } from '../lib'
 import type { TLReactCustomEvents } from '../types'
 import type { TLReactCustomEvents } from '../types'
 
 
 export function useShapeEvents<S extends TLReactShape>(shape: S) {
 export function useShapeEvents<S extends TLReactShape>(shape: S) {
+  const app = useApp()
   const { inputs, callbacks } = useRendererContext()
   const { inputs, callbacks } = useRendererContext()
 
 
   const rDoubleClickTimer = React.useRef<number>(-1)
   const rDoubleClickTimer = React.useRef<number>(-1)
 
 
   const events = React.useMemo(() => {
   const events = React.useMemo(() => {
     const onPointerMove: TLReactCustomEvents['pointer'] = e => {
     const onPointerMove: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       callbacks.onPointerMove?.({ type: TLTargetType.Shape, shape, order }, e)
       callbacks.onPointerMove?.({ type: TLTargetType.Shape, shape, order }, e)
       e.order = order + 1
       e.order = order + 1
     }
     }
 
 
     const onPointerDown: TLReactCustomEvents['pointer'] = e => {
     const onPointerDown: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
       if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
       callbacks.onPointerDown?.({ type: TLTargetType.Shape, shape, order }, e)
       callbacks.onPointerDown?.({ type: TLTargetType.Shape, shape, order }, e)
@@ -25,6 +35,10 @@ export function useShapeEvents<S extends TLReactShape>(shape: S) {
     }
     }
 
 
     const onPointerUp: TLReactCustomEvents['pointer'] = e => {
     const onPointerUp: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
       if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
       callbacks.onPointerUp?.({ type: TLTargetType.Shape, shape, order }, e)
       callbacks.onPointerUp?.({ type: TLTargetType.Shape, shape, order }, e)
@@ -42,12 +56,20 @@ export function useShapeEvents<S extends TLReactShape>(shape: S) {
     }
     }
 
 
     const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
     const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       callbacks.onPointerEnter?.({ type: TLTargetType.Shape, shape, order }, e)
       callbacks.onPointerEnter?.({ type: TLTargetType.Shape, shape, order }, e)
       e.order = order + 1
       e.order = order + 1
     }
     }
 
 
     const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
     const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
+      if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
+        return
+      }
+
       const { order = 0 } = e
       const { order = 0 } = e
       callbacks.onPointerLeave?.({ type: TLTargetType.Shape, shape, order }, e)
       callbacks.onPointerLeave?.({ type: TLTargetType.Shape, shape, order }, e)
       e.order = order + 1
       e.order = order + 1

Fișier diff suprimat deoarece este prea mare
+ 373 - 420
yarn.lock


Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff