Compare commits

...
7 Commits
Author SHA1 Message Date
Nathan.fooo eac878d563 fix: import document from database row (#4295)
* fix: import document from database row

* chore: update test

* chore: fix test

* chore: fix test

* chore: fix test

* chore: fix local user on appflowy cloud error

* chore: clippy

* chore: bump pubspec version
2024-01-04 08:02:12 +08:00
Nathan.fooo de08c01c4c chore: bump version (#4294)
* chore: bump version

* chore: bump version
2024-01-03 12:35:26 +08:00
Nathan.fooo 7937fd1f3a fix: 040 bugs (#4285)
* test: add tests

* chore: set maximum log files

* fix: import row document

* chore: bump client api

* chore: fix analyzer

* chore: fix flutter unit test
2024-01-03 11:41:29 +08:00
maTh eef5c2bf66 fix: more labels translated to German and improved (#4261) 2024-01-01 13:33:28 +08:00
dependabot[bot] 9c769cd7e5 chore: bump @babel/traverse in /frontend/appflowy_tauri (#4260)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.21.5 to 7.23.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.7/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-31 13:42:43 +08:00
dependabot[bot] eac58dc212 chore: bump @tauri-apps/cli in /frontend/appflowy_tauri (#4263)
Bumps [@tauri-apps/cli](https://github.com/tauri-apps/tauri) from 1.3.1 to 1.5.6.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/cli.js-v1.3.1...@tauri-apps/cli-v1.5.6)

---
updated-dependencies:
- dependency-name: "@tauri-apps/cli"
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-31 13:42:11 +08:00
nathan d3241cdecb chore: update changelog 2023-12-31 13:41:17 +08:00
49 changed files with 1182 additions and 559 deletions

No files matched your search

+7
View File
@@ -1,6 +1,13 @@
# Release Notes
## Version 0.4.1 - 01/03/2024
### Bug fixes
- Fix import AppFlowy data folder
## Version 0.4.0 - 12/30/2023
1. Added capability to import data from an AppFlowy data folder. For detailed information, please see [AppFlowy Data Storage Documentation](https://docs.appflowy.io/docs/appflowy/product/data-storage).
2. Enhanced user interface and fixed various bugs.
3. Improved the efficiency of data synchronization in AppFlowy Cloud
## Version 0.3.9.1 - 12/07/2023
+1 -1
View File
@@ -12,7 +12,7 @@
"program": "./lib/main.dart",
"type": "dart",
"env": {
"RUST_LOG": "debug",
"RUST_LOG": "trace",
"RUST_BACKTRACE": "1"
},
// uncomment the following line to testing performance.
+1 -1
View File
@@ -25,7 +25,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.4.0"
APPFLOWY_VERSION = "0.4.1"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
PRODUCT_NAME = "AppFlowy"
MACOSX_DEPLOYMENT_TARGET = "11.0"
@@ -7,6 +7,7 @@ import 'package:appflowy_backend/appflowy_backend.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'deps_resolver.dart';
import 'entry_point.dart';
@@ -83,6 +84,12 @@ class FlowyRunner {
rustEnvs: rustEnvsBuilder?.call() ?? {},
);
if (!mode.isUnitTest) {
// Unit test can't use the package_info_plus plugin
config.rustEnvs["APP_VERSION"] =
await PackageInfo.fromPlatform().then((value) => value.version);
}
// Specify the env
await initGetIt(getIt, mode, f, config);
await didInitGetItCallback?.call();
+1 -1
View File
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.4.0
version: 0.4.1
environment:
flutter: ">=3.18.0-0.2.pre"
+1 -1
View File
@@ -79,7 +79,7 @@
},
"devDependencies": {
"@svgr/plugin-svgo": "^8.0.1",
"@tauri-apps/cli": "^1.2.2",
"@tauri-apps/cli": "^1.5.6",
"@types/google-protobuf": "^3.15.6",
"@types/is-hotkey": "^0.1.7",
"@types/jest": "^29.5.3",
+132 -53
View File
@@ -1,5 +1,9 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
'@emoji-mart/data':
specifier: ^1.1.2
@@ -181,8 +185,8 @@ devDependencies:
specifier: ^8.0.1
version: 8.0.1(@svgr/core@7.0.0)
'@tauri-apps/cli':
specifier: ^1.2.2
version: 1.3.1
specifier: ^1.5.6
version: 1.5.6
'@types/google-protobuf':
specifier: ^3.15.6
version: 3.15.6
@@ -321,6 +325,13 @@ packages:
dependencies:
'@babel/highlight': 7.18.6
/@babel/code-frame@7.23.5:
resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.23.4
chalk: 2.4.2
/@babel/compat-data@7.21.7:
resolution: {integrity: sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==}
engines: {node: '>=6.9.0'}
@@ -337,7 +348,7 @@ packages:
'@babel/helpers': 7.21.5
'@babel/parser': 7.21.8
'@babel/template': 7.20.7
'@babel/traverse': 7.21.5
'@babel/traverse': 7.23.7
'@babel/types': 7.21.5
convert-source-map: 1.9.0
debug: 4.3.4
@@ -356,6 +367,15 @@ packages:
'@jridgewell/trace-mapping': 0.3.18
jsesc: 2.5.2
/@babel/generator@7.23.6:
resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.23.6
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.18
jsesc: 2.5.2
/@babel/helper-compilation-targets@7.21.5(@babel/core@7.21.8):
resolution: {integrity: sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==}
engines: {node: '>=6.9.0'}
@@ -373,18 +393,22 @@ packages:
resolution: {integrity: sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==}
engines: {node: '>=6.9.0'}
/@babel/helper-function-name@7.21.0:
resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==}
/@babel/helper-environment-visitor@7.22.20:
resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.20.7
'@babel/types': 7.21.5
/@babel/helper-hoist-variables@7.18.6:
resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
/@babel/helper-function-name@7.23.0:
resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.5
'@babel/template': 7.22.15
'@babel/types': 7.23.6
/@babel/helper-hoist-variables@7.22.5:
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.23.6
/@babel/helper-module-imports@7.21.4:
resolution: {integrity: sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==}
@@ -402,7 +426,7 @@ packages:
'@babel/helper-split-export-declaration': 7.18.6
'@babel/helper-validator-identifier': 7.19.1
'@babel/template': 7.20.7
'@babel/traverse': 7.21.5
'@babel/traverse': 7.23.7
'@babel/types': 7.21.5
transitivePeerDependencies:
- supports-color
@@ -423,14 +447,28 @@ packages:
dependencies:
'@babel/types': 7.21.5
/@babel/helper-split-export-declaration@7.22.6:
resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.23.6
/@babel/helper-string-parser@7.21.5:
resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==}
engines: {node: '>=6.9.0'}
/@babel/helper-string-parser@7.23.4:
resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
engines: {node: '>=6.9.0'}
/@babel/helper-validator-identifier@7.19.1:
resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
engines: {node: '>=6.9.0'}
/@babel/helper-validator-identifier@7.22.20:
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
engines: {node: '>=6.9.0'}
/@babel/helper-validator-option@7.21.0:
resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==}
engines: {node: '>=6.9.0'}
@@ -440,7 +478,7 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.20.7
'@babel/traverse': 7.21.5
'@babel/traverse': 7.23.7
'@babel/types': 7.21.5
transitivePeerDependencies:
- supports-color
@@ -453,6 +491,14 @@ packages:
chalk: 2.4.2
js-tokens: 4.0.0
/@babel/highlight@7.23.4:
resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.22.20
chalk: 2.4.2
js-tokens: 4.0.0
/@babel/parser@7.21.8:
resolution: {integrity: sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==}
engines: {node: '>=6.0.0'}
@@ -460,6 +506,13 @@ packages:
dependencies:
'@babel/types': 7.21.5
/@babel/parser@7.23.6:
resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.23.6
/@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.8):
resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
peerDependencies:
@@ -629,18 +682,26 @@ packages:
'@babel/parser': 7.21.8
'@babel/types': 7.21.5
/@babel/traverse@7.21.5:
resolution: {integrity: sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==}
/@babel/template@7.22.15:
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.21.4
'@babel/generator': 7.21.5
'@babel/helper-environment-visitor': 7.21.5
'@babel/helper-function-name': 7.21.0
'@babel/helper-hoist-variables': 7.18.6
'@babel/helper-split-export-declaration': 7.18.6
'@babel/parser': 7.21.8
'@babel/types': 7.21.5
'@babel/code-frame': 7.23.5
'@babel/parser': 7.23.6
'@babel/types': 7.23.6
/@babel/traverse@7.23.7:
resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.23.5
'@babel/generator': 7.23.6
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-function-name': 7.23.0
'@babel/helper-hoist-variables': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.23.6
'@babel/types': 7.23.6
debug: 4.3.4
globals: 11.12.0
transitivePeerDependencies:
@@ -654,6 +715,14 @@ packages:
'@babel/helper-validator-identifier': 7.19.1
to-fast-properties: 2.0.0
/@babel/types@7.23.6:
resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-string-parser': 7.23.4
'@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0
/@bcoe/v8-coverage@0.2.3:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
@@ -2005,8 +2074,8 @@ packages:
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
dev: false
/@tauri-apps/cli-darwin-arm64@1.3.1:
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
/@tauri-apps/cli-darwin-arm64@1.5.6:
resolution: {integrity: sha512-NNvG3XLtciCMsBahbDNUEvq184VZmOveTGOuy0So2R33b/6FDkuWaSgWZsR1mISpOuP034htQYW0VITCLelfqg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@@ -2014,8 +2083,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-darwin-x64@1.3.1:
resolution: {integrity: sha512-fKcAUPVFO3jfDKXCSDGY0MhZFF/wDtx3rgFnogWYu4knk38o9RaqRkvMvqJhLYPuWaEM5h6/z1dRrr9KKCbrVg==}
/@tauri-apps/cli-darwin-x64@1.5.6:
resolution: {integrity: sha512-nkiqmtUQw3N1j4WoVjv81q6zWuZFhBLya/RNGUL94oafORloOZoSY0uTZJAoeieb3Y1YK0rCHSDl02MyV2Fi4A==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@@ -2023,8 +2092,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm-gnueabihf@1.3.1:
resolution: {integrity: sha512-+4H0dv8ltJHYu/Ma1h9ixUPUWka9EjaYa8nJfiMsdCI4LJLNE6cPveE7RmhZ59v9GW1XB108/k083JUC/OtGvA==}
/@tauri-apps/cli-linux-arm-gnueabihf@1.5.6:
resolution: {integrity: sha512-z6SPx+axZexmWXTIVPNs4Tg7FtvdJl9EKxYN6JPjOmDZcqA13iyqWBQal2DA/GMZ1Xqo3vyJf6EoEaKaliymPQ==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
@@ -2032,8 +2101,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm64-gnu@1.3.1:
resolution: {integrity: sha512-Pj3odVO1JAxLjYmoXKxcrpj/tPxcA8UP8N06finhNtBtBaxAjrjjxKjO4968KB0BUH7AASIss9EL4Tr0FGnDuw==}
/@tauri-apps/cli-linux-arm64-gnu@1.5.6:
resolution: {integrity: sha512-QuQjMQmpsCbzBrmtQiG4uhnfAbdFx3nzm+9LtqjuZlurc12+Mj5MTgqQ3AOwQedH3f7C+KlvbqD2AdXpwTg7VA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -2041,8 +2110,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm64-musl@1.3.1:
resolution: {integrity: sha512-tA0JdDLPFaj42UDIVcF2t8V0tSha40rppcmAR/MfQpTCxih6399iMjwihz9kZE1n4b5O4KTq9GliYo50a8zYlQ==}
/@tauri-apps/cli-linux-arm64-musl@1.5.6:
resolution: {integrity: sha512-8j5dH3odweFeom7bRGlfzDApWVOT4jIq8/214Wl+JeiNVehouIBo9lZGeghZBH3XKFRwEvU23i7sRVjuh2s8mg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -2050,8 +2119,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-x64-gnu@1.3.1:
resolution: {integrity: sha512-FDU+Mnvk6NLkqQimcNojdKpMN4Y3W51+SQl+NqG9AFCWprCcSg62yRb84751ujZuf2MGT8HQOfmd0i77F4Q3tQ==}
/@tauri-apps/cli-linux-x64-gnu@1.5.6:
resolution: {integrity: sha512-gbFHYHfdEGW0ffk8SigDsoXks6USpilF6wR0nqB/JbWzbzFR/sBuLVNQlJl1RKNakyJHu+lsFxGy0fcTdoX8xA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -2059,8 +2128,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-x64-musl@1.3.1:
resolution: {integrity: sha512-MpO3akXFmK8lZYEbyQRDfhdxz1JkTBhonVuz5rRqxwA7gnGWHa1aF1+/2zsy7ahjB2tQ9x8DDFDMdVE20o9HrA==}
/@tauri-apps/cli-linux-x64-musl@1.5.6:
resolution: {integrity: sha512-9v688ogoLkeFYQNgqiSErfhTreLUd8B3prIBSYUt+x4+5Kcw91zWvIh+VSxL1n3KCGGsM7cuXhkGPaxwlEh1ug==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -2068,8 +2137,17 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-ia32-msvc@1.3.1:
resolution: {integrity: sha512-9Boeo3K5sOrSBAZBuYyGkpV2RfnGQz3ZhGJt4hE6P+HxRd62lS6+qDKAiw1GmkZ0l1drc2INWrNeT50gwOKwIQ==}
/@tauri-apps/cli-win32-arm64-msvc@1.5.6:
resolution: {integrity: sha512-DRNDXFNZb6y5IZrw+lhTTA9l4wbzO4TNRBAlHAiXUrH+pRFZ/ZJtv5WEuAj9ocVSahVw2NaK5Yaold4NPAxHog==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@tauri-apps/cli-win32-ia32-msvc@1.5.6:
resolution: {integrity: sha512-oUYKNR/IZjF4fsOzRpw0xesl2lOjhsQEyWlgbpT25T83EU113Xgck9UjtI7xemNI/OPCv1tPiaM1e7/ABdg5iA==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@@ -2077,8 +2155,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-x64-msvc@1.3.1:
resolution: {integrity: sha512-wMrTo91hUu5CdpbElrOmcZEoJR4aooTG+fbtcc87SMyPGQy1Ux62b+ZdwLvL1sVTxnIm//7v6QLRIWGiUjCPwA==}
/@tauri-apps/cli-win32-x64-msvc@1.5.6:
resolution: {integrity: sha512-RmEf1os9C8//uq2hbjXi7Vgz9ne7798ZxqemAZdUwo1pv3oLVZSz1/IvZmUHPdy2e6zSeySqWu1D0Y3QRNN+dg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -2086,20 +2164,21 @@ packages:
dev: true
optional: true
/@tauri-apps/cli@1.3.1:
resolution: {integrity: sha512-o4I0JujdITsVRm3/0spfJX7FcKYrYV1DXJqzlWIn6IY25/RltjU6qbC1TPgVww3RsRX63jyVUTcWpj5wwFl+EQ==}
/@tauri-apps/cli@1.5.6:
resolution: {integrity: sha512-k4Y19oVCnt7WZb2TnDzLqfs7o98Jq0tUoVMv+JQSzuRDJqaVu2xMBZ8dYplEn+EccdR5SOMyzaLBJWu38TVK1A==}
engines: {node: '>= 10'}
hasBin: true
optionalDependencies:
'@tauri-apps/cli-darwin-arm64': 1.3.1
'@tauri-apps/cli-darwin-x64': 1.3.1
'@tauri-apps/cli-linux-arm-gnueabihf': 1.3.1
'@tauri-apps/cli-linux-arm64-gnu': 1.3.1
'@tauri-apps/cli-linux-arm64-musl': 1.3.1
'@tauri-apps/cli-linux-x64-gnu': 1.3.1
'@tauri-apps/cli-linux-x64-musl': 1.3.1
'@tauri-apps/cli-win32-ia32-msvc': 1.3.1
'@tauri-apps/cli-win32-x64-msvc': 1.3.1
'@tauri-apps/cli-darwin-arm64': 1.5.6
'@tauri-apps/cli-darwin-x64': 1.5.6
'@tauri-apps/cli-linux-arm-gnueabihf': 1.5.6
'@tauri-apps/cli-linux-arm64-gnu': 1.5.6
'@tauri-apps/cli-linux-arm64-musl': 1.5.6
'@tauri-apps/cli-linux-x64-gnu': 1.5.6
'@tauri-apps/cli-linux-x64-musl': 1.5.6
'@tauri-apps/cli-win32-arm64-msvc': 1.5.6
'@tauri-apps/cli-win32-ia32-msvc': 1.5.6
'@tauri-apps/cli-win32-x64-msvc': 1.5.6
dev: true
/@tootallnate/once@2.0.0:
@@ -4667,7 +4746,7 @@ packages:
'@babel/generator': 7.21.5
'@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8)
'@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.21.8)
'@babel/traverse': 7.21.5
'@babel/traverse': 7.23.7
'@babel/types': 7.21.5
'@jest/expect-utils': 29.5.0
'@jest/transform': 29.5.0
+72 -58
View File
@@ -139,7 +139,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"reqwest",
@@ -193,7 +193,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -204,7 +204,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -352,7 +352,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -734,7 +734,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
@@ -831,7 +831,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -840,6 +840,7 @@ dependencies = [
"parking_lot",
"serde",
"serde_json",
"serde_repr",
"thiserror",
"tokio",
"tokio-stream",
@@ -850,7 +851,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -879,7 +880,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"collab",
@@ -897,7 +898,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"bytes",
@@ -911,7 +912,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"chrono",
@@ -948,7 +949,7 @@ dependencies = [
[[package]]
name = "collab-persistence"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -969,7 +970,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -995,7 +996,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"collab",
@@ -1253,7 +1254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -1317,7 +1318,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -1328,7 +1329,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
dependencies = [
"darling_core",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -1353,10 +1354,11 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
"bincode",
"chrono",
"collab-entity",
"serde",
@@ -1431,7 +1433,7 @@ dependencies = [
"diesel_table_macro_syntax",
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -1451,7 +1453,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
dependencies = [
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -2320,7 +2322,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -2649,7 +2651,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"futures-util",
@@ -2665,7 +2667,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
@@ -3087,7 +3089,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"reqwest",
@@ -3893,7 +3895,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -4103,7 +4105,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -4257,7 +4259,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -4305,7 +4307,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -4422,7 +4424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282"
dependencies = [
"proc-macro2",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -4476,9 +4478,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.63"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db"
dependencies = [
"unicode-ident",
]
@@ -4510,7 +4512,7 @@ dependencies = [
"prost",
"prost-types",
"regex",
"syn 2.0.32",
"syn 2.0.46",
"tempfile",
"which",
]
@@ -4525,7 +4527,7 @@ dependencies = [
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -4681,9 +4683,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.30"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5907a1b7c277254a8b15170f6e7c97cfa60ee7872a3217663bb81151e48184bb"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -4817,7 +4819,7 @@ dependencies = [
[[package]]
name = "realtime-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"bincode",
@@ -4839,7 +4841,7 @@ dependencies = [
[[package]]
name = "realtime-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"bincode",
@@ -5391,7 +5393,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -5407,13 +5409,13 @@ dependencies = [
[[package]]
name = "serde_repr"
version = "0.1.16"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -5462,7 +5464,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -5546,7 +5548,7 @@ dependencies = [
[[package]]
name = "shared_entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
@@ -5904,7 +5906,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -5926,9 +5928,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.32"
version = "2.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e"
dependencies = [
"proc-macro2",
"quote",
@@ -6309,7 +6311,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -6401,7 +6403,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -6562,11 +6564,12 @@ dependencies = [
[[package]]
name = "tracing-appender"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
dependencies = [
"crossbeam-channel",
"thiserror",
"time",
"tracing-subscriber",
]
@@ -6579,7 +6582,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
@@ -6596,7 +6599,7 @@ dependencies = [
"time",
"tracing",
"tracing-core",
"tracing-log",
"tracing-log 0.1.3",
"tracing-subscriber",
]
@@ -6621,6 +6624,17 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-serde"
version = "0.1.3"
@@ -6633,9 +6647,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.17"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"matchers",
"nu-ansi-term",
@@ -6648,7 +6662,7 @@ dependencies = [
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
"tracing-log 0.2.0",
"tracing-serde",
]
@@ -6995,7 +7009,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
"wasm-bindgen-shared",
]
@@ -7029,7 +7043,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -7436,7 +7450,7 @@ dependencies = [
[[package]]
name = "workspace-template"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"async-trait",
@@ -7562,7 +7576,7 @@ checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.32",
"syn 2.0.46",
]
[[package]]
+9 -9
View File
@@ -57,7 +57,7 @@ custom-protocol = ["tauri/custom-protocol"]
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a455c9de8e6448cec956da5a00ba5cc136ed7274" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "40daff472d026d155fc703aacce899b1c5ab98ea" }
# Please use the following script to update collab.
# Working directory: frontend
#
@@ -67,14 +67,14 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a45
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
+314 -76
View File
@@ -303,12 +303,13 @@
"importAppFlowyData": "Daten von einem externen AppFlowy Ordner importieren.",
"importAppFlowyDataDescription": "Daten von einem externen AppFlowy Ordner kopieren und in den aktuellen AppFlowy Datenordner importieren.",
"importSuccess": "Der AppFlowy Datenordner wurde erfolgreich importiert",
"importFailed": "Der AppFlowy Datenordner-Import ist fehlgeschlagen"
"importFailed": "Der AppFlowy Datenordner-Import ist fehlgeschlagen",
"importGuide": "Für weitere Details, bitte das verlinkte Dokument prüfen"
},
"notifications": {
"enableNotifications": {
"label": "Benachrichtigungen aktivieren",
"hint": "Ausschalten, um die lokalen Benachrichtigungen abzuschalten"
"hint": "Ausschalten, damit die lokalen Benachrichtigungen nicht mehr angezeigt werden"
}
},
"appearance": {
@@ -323,8 +324,35 @@
"dark": "Dunkles Design",
"system": "Automatisch, wie Betriebssystem"
},
"documentSettings": {
"cursorColor": "Dokument Cursor-Farbe",
"selectionColor": "Dokument Auswahl-Farbe",
"hexEmptyError": "Hex-Farbe darf nicht leer sein",
"hexLengthError": "Hex-Wert muss 6 Zeichen lang sein",
"hexInvalidError": "Ungültiger Hex-Wert",
"opacityEmptyError": "Transparenz darf nicht leer sein",
"opacityRangeError": "Transparenz ist ein Wert zwischen 1 und 100",
"app": "App",
"flowy": "Flowy",
"apply": "Apply"
},
"layoutDirection": {
"label": "Layoutrichtung",
"hint": "Steuere den Umlauf der Inhalte auf deinem Bildschirm: Von Links nach Rechts oder von Rechts nach Links.",
"ltr": "LNR",
"rtl": "RNL"
},
"textDirection": {
"label": "Textrichtung",
"hint": "Wie soll der Text laufen: von Links nach Rechts oder von Rechts nach Links?",
"ltr": "LNR",
"rtl": "RNL",
"auto": "AUTO",
"fallback": "Wie die Layoutrichtung"
},
"themeUpload": {
"button": "Hochladen",
"uploadTheme": "Theme hochladen",
"description": "Laden Sie Ihr eigenes AppFlowy-Theme über die Schaltfläche unten hoch.",
"failure": "Das hochgeladene Theme hatte ein ungültiges Format.",
"loading": "Bitte warten Sie, während wir Ihr Theme validieren und hochladen ...",
@@ -333,78 +361,123 @@
"filePickerDialogTitle": "Wählen Sie eine .flowy_plugin-Datei",
"urlUploadFailure": "URL konnte nicht geöffnet werden: {}"
},
"theme": "Thema",
"theme": "Theme",
"builtInsLabel": "Integrierte Themes",
"pluginsLabel": "Plugins",
"lightLabel": "Heller Modus",
"darkLabel": "Dunkler Modus"
"dateFormat": {
"label": "Datumsformat",
"local": "Lokal",
"us": "US",
"iso": "ISO",
"friendly": "Freundlich",
"dmy": "T/M/J"
},
"timeFormat": {
"label": "Zeitformat",
"twelveHour": "12 Stunden",
"twentyFourHour": "24 Stunden"
},
"showNamingDialogWhenCreatingPage": "Zeige Bennenungsfenster wenn eine neue Seite erstellt wird"
},
"files": {
"copy": "Kopieren",
"defaultLocation": "Lesen Sie Dateien und Datenspeicherort",
"exportData": "Exportieren Sie Ihre Daten",
"doubleTapToCopy": "Tippen Sie zweimal, um den Pfad zu kopieren",
"restoreLocation": "Stellen Sie den AppFlowy-Standardpfad wieder her",
"customizeLocation": "Öffnen Sie einen anderen Ordner",
"defaultLocation": "Dateien und Speicherort",
"exportData": "Daten exportieren",
"doubleTapToCopy": "Zweimal tippen, um den Pfad zu kopieren",
"restoreLocation": "AppFlowy-Standardpfad wiederherstellen",
"customizeLocation": "Einen anderen Ordner öffnen",
"restartApp": "Bitte starten Sie die App neu, damit die Änderungen wirksam werden.",
"exportDatabase": "Datenbank exportieren",
"selectFiles": "Wählen Sie die Dateien aus, die exportiert werden sollen",
"selectAll": "Wählen Sie Alle",
"selectFiles": "Dateien auswählen, die exportiert werden sollen",
"selectAll": "Alle auswählen",
"deselectAll": "Alle abwählen",
"createNewFolder": "Einen neuen Ordner erstellen",
"createNewFolderDesc": "Teilen Sie uns mit, wo Sie Ihre Daten speichern möchten",
"defineWhereYourDataIsStored": "Legen Sie fest, wo Ihre Daten gespeichert werden",
"createNewFolderDesc": "Wo sollen die Daten gespeichert werden?",
"defineWhereYourDataIsStored": "Wo sind die Daten gespeichert?",
"open": "Offen",
"openFolder": "Öffnen Sie einen vorhandenen Ordner",
"openFolderDesc": "Lesen Sie es und schreiben Sie es in Ihren vorhandenen AppFlowy-Ordner",
"openFolder": "Einen vorhandenen Ordner öffnen",
"openFolderDesc": "Öffnen und speichern im vorhandenen AppFlowy-Ordner",
"folderHintText": "Ordnernamen",
"location": "Erstellen eines neuen Ordners",
"locationDesc": "Wählen Sie einen Namen für Ihren AppFlowy-Datenordner",
"browser": "Durchsuche",
"location": "Ein neuen Ordner erstellen",
"locationDesc": "Einen Namen für den AppFlowy-Datenordner festlegen",
"browser": "Durchsuchen",
"create": "Erstellen",
"set": "Festlegen",
"folderPath": "Pfad zum Speichern Ihres Ordners",
"folderPath": "Pfad zum Speichern des Ordners",
"locationCannotBeEmpty": "Der Pfad darf nicht leer sein",
"pathCopiedSnackbar": "Dateispeicherpfad in Zwischenablage kopiert!",
"changeLocationTooltips": "Ändern Sie das Datenverzeichnis",
"changeLocationTooltips": "Datenverzeichnis ändern",
"change": "Ändern",
"openLocationTooltips": "Öffnen Sie ein anderes Datenverzeichnis",
"openLocationTooltips": "Win anderes Datenverzeichnis öffnen",
"openCurrentDataFolder": "Aktuelles Datenverzeichnis öffnen",
"recoverLocationTooltips": "Zurücksetzen auf das Standarddatenverzeichnis von AppFlowy",
"exportFileSuccess": "Datei erfolgreich exportieren!",
"exportFileFail": "Datei exportieren fehlgeschlagen!",
"exportFileSuccess": "Datei erfolgreich exportiert!",
"exportFileFail": "Datei-Export fehlgeschlagen!",
"export": "Export"
},
"user": {
"name": "Name",
"email": "E-Mail",
"selectAnIcon": "Wählen Sie ein Symbol aus",
"pleaseInputYourOpenAIKey": "Bitte geben Sie Ihren OpenAI-Schlüssel ein"
"tooltipSelectIcon": "Symbol auswählen",
"selectAnIcon": "Ein Symbol auswählen",
"pleaseInputYourOpenAIKey": "Bitte geben Sie Ihren OpenAI-Schlüssel ein",
"pleaseInputYourStabilityAIKey": "Bitte geben Sie Ihren Stability AI Schlüssel ein",
"clickToLogout": "Klicken, um den aktuellen Nutzer auszulogen"
},
"shortcuts": {
"shortcutsLabel": "Verknüpfungen",
"shortcutsLabel": "Tastenkürzel",
"command": "Befehl",
"keyBinding": "Tastenkombination",
"addNewCommand": "Neuen Befehl hinzufügen",
"updateShortcutStep": "Drücken Sie die gewünschte Tastenkombination und drücken Sie ENTER",
"updateShortcutStep": "Die gewünschte Tastenkombination drücken und mit ENTER bestätigen",
"shortcutIsAlreadyUsed": "Diese Verknüpfung wird bereits verwendet für: {conflict}",
"resetToDefault": "Zurücksetzen"
"resetToDefault": "Zurücksetzen",
"couldNotLoadErrorMsg": "Tastenkürzel konnten nicht geladen werden. Bitte nochmal versuchen.",
"couldNotSaveErrorMsg": "Tastenkürzel konnten nicht gespeichert werden. Bitte nochmal versuchen."
},
"mobile": {
"personalInfo": "Persönliche Informationen",
"username": "Nutzername",
"usernameEmptyError": "Der Nutzername darf nicht leer sein",
"about": "Über",
"pushNotifications": "Push Benachrichtigungen",
"support": "Support",
"joinDiscord": "Komm zu uns bei Discord",
"privacyPolicy": "Datenschutz",
"userAgreement": "Nutzungsbedingungen",
"userprofileError": "Das Nutzerprofil konnte nicht geladen werden",
"userprofileErrorDescription": "Bitte abmelden und wieder anmelden, um zu prüfen ob das Problem weiterhin bestehen bleibt.",
"selectLayout": "Layout auswählen",
"selectStartingDay": "Ersten Tag auswählen"
}
},
"grid": {
"deleteView": "Möchten Sie diese Ansicht wirklich löschen?",
"createView": "Neu",
"title": {
"placeholder": "Unbenannt"
},
"settings": {
"filter": "Filter",
"sort": "Sortieren",
"sortBy": "Sortiere nach",
"properties": "Eigenschaften",
"reorderPropertiesTooltip": "Ziehen Sie, um die Eigenschaften neu anzuordnen",
"reorderPropertiesTooltip": "Ziehen, um die Eigenschaften neu anzuordnen",
"group": "Gruppe",
"addFilter": "Filter hinzufügen",
"deleteFilter": "Filter löschen",
"filterBy": "Filtern nach...",
"typeAValue": "Geben Sie einen Wert ein...",
"typeAValue": "Einen Wert eingeben...",
"layout": "Layout",
"databaseLayout": "Layout"
"databaseLayout": "Layout",
"viewList": "Datenbank-Ansichten",
"editView": "Ansicht editieren",
"boardSettings": "Board-Einstellungen",
"calendarSettings": "Kalender-Einstellungen",
"createView": "New Ansicht",
"duplicateView": "Ansicht duplizieren",
"deleteView": "Anslicht löschen",
"numberOfVisibleFields": "{} zeigen"
},
"textFilter": {
"contains": "Enthält",
@@ -446,8 +519,19 @@
"isEmpty": "Ist leer",
"isNotEmpty": "Ist nicht leer"
},
"dateFilter": {
"is": "Ist",
"before": "Ist bevor",
"after": "Ist nach",
"onOrBefore": "Ist am oder bevor",
"onOrAfter": "Ist am oder nach",
"between": "Ist zwischen",
"empty": "Ist leer",
"notEmpty": "Ist nicht leer"
},
"field": {
"hide": "Verstecken",
"show": "Anzeigen",
"insertLeft": "Links einfügen",
"insertRight": "Rechts einfügen",
"duplicate": "Duplikat",
@@ -465,6 +549,7 @@
"numberFormat": "Zahlenformat",
"dateFormat": "Datumsformat",
"includeTime": "Zeit einbeziehen",
"isRange": "Enddatum",
"dateFormatFriendly": "Monat Tag, Jahr",
"dateFormatISO": "Jahr-Monat-Tag",
"dateFormatLocal": "Monat/Tag/Jahr",
@@ -474,32 +559,64 @@
"invalidTimeFormat": "Ungültiges Format",
"timeFormatTwelveHour": "12 Stunden",
"timeFormatTwentyFourHour": "24 Stunden",
"clearDate": "Datum löschen",
"dateTime": "Datum und Zeit",
"startDateTime": "Beginn Datum und Zeit",
"endDateTime": "Ende Datum und Zeit",
"failedToLoadDate": "Laden des Datums ist fehlgeschlagen",
"selectTime": "Auswahl Zeit",
"selectDate": "Auswahl Datum",
"visibility": "Sichtbarkeit",
"propertyType": "Eigenschaftstyp",
"addSelectOption": "Fügen Sie eine Option hinzu",
"typeANewOption": "Eine neue Option eingeben",
"optionTitle": "Optionen",
"addOption": "Option hinzufügen",
"editProperty": "Eigenschaft bearbeiten",
"newProperty": "Neue Eigenschaft",
"deleteFieldPromptMessage": "Bist du dir sicher? Diese Eigenschaft wird gelöscht"
"deleteFieldPromptMessage": "Sicher? Diese Eigenschaft wird gelöscht",
"newColumn": "Neue Spalte",
"format": "Format"
},
"rowPage": {
"newField": "Ein neues Feld hinzufügen",
"fieldDragElementTooltip": "Klicken, um das Menü zu öffnen",
"showHiddenFields": {
"one": "Zeige {count} verstecktes Feld",
"many": "Zeige {count} versteckte Felder",
"other": "Zeige {count} versteckte Felder"
},
"hideHiddenFields": {
"one": "Blende {count} verstecktes Feld aus",
"many": "Blende {count} versteckte Felder aus",
"other": "Blende {count} versteckte Felder aus"
}
},
"sort": {
"ascending": "Aufsteigend",
"descending": "Absteigend",
"addSort": "Sortierung hinzufügen",
"deleteSort": "Sortierung löschen"
"deleteAllSorts": "Alle Sortierungen entfernen",
"addSort": "Sortierung hinzufügen"
},
"row": {
"duplicate": "Duplikat",
"delete": "Löschen",
"titlePlaceholder": "Unbenannt",
"textPlaceholder": "Leer",
"copyProperty": "Eigenschaft in die Zwischenablage kopiert",
"count": "Zählen",
"newRow": "Neue Reihe",
"action": "Aktion"
"newRow": "Neue Zeile",
"action": "Aktion",
"add": "Klicken, um unten hinzuzufügen",
"drag": "Ziehen, um zu verschieben",
"dragAndClick": "Ziehen, um zu verschieben. Klicke, um das Menü zu öffnen",
"insertRecordAbove": "Füge Datensatz oben ein",
"insertRecordBelow": "Füge Datensatz unten ein"
},
"selectOption": {
"create": "Erstellen",
"purpleColor": "Lila",
"pinkColor": "Rosa",
"pinkColor": "Pink",
"lightPinkColor": "Hell-Pink",
"orangeColor": "Orange",
"yellowColor": "Gelb",
@@ -508,48 +625,62 @@
"aquaColor": "Aqua",
"blueColor": "Blau",
"deleteTag": "Tag löschen",
"colorPanelTitle": "Farben",
"colorPanelTitle": "Farbe",
"panelTitle": "Eine Option auswählen oder erstellen",
"searchOption": "Suchen Sie nach einer Option"
"searchOption": "Nach einer Option suchen",
"searchOrCreateOption": "Eine Option suchen oder erstellen...",
"createNew": "Neu erstellen",
"orSelectOne": "Oder eine Option auswählen",
"typeANewOption": "Tippe eine neue Option",
"tagName": "Tag-Name"
},
"checklist": {
"addNew": "Fügen Sie einen Artikel hinzu"
"taskHint": "Aufgbenbeschreibbung",
"addNew": "Fügen Sie einen Artikel hinzu",
"submitNewTask": "Erstellen",
"hideComplete": "Blende abgeschlossene Aufgaben aus",
"showComplete": "Zeige alle Aufgaben"
},
"menuName": "Netz",
"menuName": "Raster",
"referencedGridPrefix": "Sicht von"
},
"document": {
"menuName": "Dokumentieren",
"menuName": "Dokument",
"date": {
"timeHintTextInTwelveHour": "13:00 Uhr",
"timeHintTextInTwentyFourHour": "13:00"
},
"slashMenu": {
"board": {
"selectABoardToLinkTo": "Wählen Sie ein Board aus, zu dem Sie einen Link erstellen möchten",
"createANewBoard": "Erstellen Sie ein neues Board"
"selectABoardToLinkTo": "Ein Board zum Verknüpfen auswählen",
"createANewBoard": "Ein neues Board erstellen"
},
"grid": {
"selectAGridToLinkTo": "Wählen Sie ein Raster zum Verknüpfen aus",
"createANewGrid": "Erstellen Sie ein neues Raster"
"selectAGridToLinkTo": "Ein Raster zum Verknüpfen auswählen",
"createANewGrid": "Ein neues Raster erstellen"
},
"calendar": {
"selectACalendarToLinkTo": "Wählen Sie einen Kalender aus, mit dem Sie eine Verknüpfung erstellen möchten",
"createANewCalendar": "Erstellen Sie einen neuen Kalender"
"selectACalendarToLinkTo": "Einen Kalender zum Verknüpfen auswählen",
"createANewCalendar": "Einen neuen Kalender erstellen"
},
"document": {
"selectADocumentToLinkTo": "Ein Raster zum Verknüpfen auswählen"
}
},
"selectionMenu": {
"outline": "Umriss"
"outline": "Gliederung",
"codeBlock": "Code Block"
},
"plugins": {
"referencedBoard": "Referenziertes Board",
"referencedGrid": "Referenziertes Raster",
"referencedCalendar": "Referenzierter Kalender",
"referencedDocument": "Referenziertes Dokument",
"autoGeneratorMenuItemName": "OpenAI-Autor",
"autoGeneratorTitleName": "OpenAI: Bitten Sie die KI, etwas zu schreiben ...",
"autoGeneratorLearnMore": "Erfahren Sie mehr",
"autoGeneratorGenerate": "Generieren",
"autoGeneratorHintText": "Fragen Sie OpenAI ...",
"autoGeneratorTitleName": "OpenAI: Die KI bitten, etwas zu schreiben ...",
"autoGeneratorLearnMore": "Mehr erfahren",
"autoGeneratorGenerate": "Erstellen",
"autoGeneratorHintText": "OpenAI fragen ...",
"autoGeneratorCantGetOpenAIKey": "Der OpenAI-Schlüssel kann nicht abgerufen werden",
"autoGeneratorRewrite": "Umschreiben",
"smartEdit": "KI-Assistenten",
@@ -557,14 +688,20 @@
"smartEditFixSpelling": "Korrigiere Rechtschreibung",
"warning": "⚠️ KI-Antworten können ungenau oder irreführend sein.",
"smartEditSummarize": "Zusammenfassen",
"smartEditImproveWriting": "Verbessern Sie das Schreiben",
"smartEditImproveWriting": "Das Geschriebene verbessern",
"smartEditMakeLonger": "Länger machen",
"smartEditCouldNotFetchResult": "Das Ergebnis konnte nicht von OpenAI abgerufen werden",
"smartEditCouldNotFetchKey": "Der OpenAI-Schlüssel konnte nicht abgerufen werden",
"smartEditDisabled": "Verbinden Sie OpenAI in den Einstellungen",
"smartEditDisabled": "OpenAI in den Einstellungen verbinden",
"discardResponse": "Möchten Sie die KI-Antworten verwerfen?",
"createInlineMathEquation": "Formel erstellen",
"fonts": "Schriftarten",
"toggleList": "Liste umschalten",
"quoteList": "Kursblatt",
"numberedList": "Nummerierte Liste",
"bulletedList": "Stichpunktliste",
"todoList": "Offene Aufgaben Liste",
"callout": "Hervorhebung",
"cover": {
"changeCover": "Titelbild wechseln",
"colors": "Farben",
@@ -575,23 +712,25 @@
"addLocalImage": "Lokales Bild hinzufügen",
"invalidImageUrl": "Ungültige Bild-URL",
"failedToAddImageToGallery": "Das Bild konnte nicht zur Galerie hinzugefügt werden",
"enterImageUrl": "Geben Sie die Bild-URL ein",
"enterImageUrl": "Bild-URL eingeben",
"add": "Hinzufügen",
"back": "Zurück",
"saveToGallery": "In der Galerie speichern",
"removeIcon": "Symbol entfernen",
"pasteImageUrl": "Bild-URL einfügen",
"or": "ODER",
"pickFromFiles": "Wählen Sie aus Dateien",
"pickFromFiles": "Dateien auswählen",
"couldNotFetchImage": "Bild konnte nicht abgerufen werden",
"imageSavingFailed": "Bildspeicherung fehlgeschlagen",
"addIcon": "Symbol hinzufügen",
"coverRemoveAlert": "Nach dem Löschen wird es aus der Abdeckung entfernt.",
"alertDialogConfirmation": "Bist du dir sicher, dass du weitermachen willst?"
"changeIcon": "Symbol wechseln",
"coverRemoveAlert": "Nach dem Löschen wird es aus dem Titelbild entfernt.",
"alertDialogConfirmation": "Sicher, dass Sie weitermachen wollen?"
},
"mathEquation": {
"name": "Mathematische Formel",
"addMathEquation": "Mathematische Formel hinzufügen",
"editMathEquation": "Bearbeiten Sie die mathematische Formel"
"editMathEquation": "Mathematische Formel bearbeiten"
},
"optionAction": {
"click": "Klicken",
@@ -599,45 +738,93 @@
"delete": "Löschen",
"duplicate": "Duplikat",
"turnInto": "Einbiegen in",
"moveUp": "Bewegen Sie sich nach oben",
"moveDown": "Sich abwärts bewegen",
"moveUp": "Nach oben verschieben",
"moveDown": "Nach unten verschieben",
"color": "Farbe",
"align": "Ausrichten",
"left": "Links",
"center": "Center",
"center": "Zentriert",
"right": "Rechts",
"defaultColor": "Standard"
},
"image": {
"copiedToPasteBoard": "Der Bildlink wurde in die Zwischenablage kopiert"
"copiedToPasteBoard": "Der Bildlink wurde in die Zwischenablage kopiert",
"addAnImage": "Ein Bild hinzufügen"
},
"urlPreview": {
"copiedToPasteBoard": "Der Link wurde in die Zwischenablage kopiert"
},
"outline": {
"addHeadingToCreateOutline": "Fügen Sie Überschriften hinzu, um ein Inhaltsverzeichnis zu erstellen."
},
"table": {
"addAfter": "Danach einfügen",
"addBefore": "Davor einfügen",
"delete": "Löschen",
"clear": "Inhalt löschen",
"duplicate": "Duplikat",
"bgColor": "Hintergrundfarbe"
},
"contextMenu": {
"copy": "Kopieren",
"cut": "Ausschneiden",
"paste": "Einfügen"
},
"action": "Aktionen",
"database": {
"selectDataSource": "Datenquelle auswählen",
"noDataSource": "Keine Datenquelle",
"selectADataSource": "Eine Datenquelle auswählen",
"toContinue": "fortfahren",
"newDatabase": "Neue Datenbank",
"linkToDatabase": "Verknüpfung zur Datenbank"
}
},
"textBlock": {
"placeholder": "Geben Sie „/“ für Befehle ein"
"placeholder": "Geben Sie „/“ für Inhaltsblöcke ein"
},
"title": {
"placeholder": "Ohne Titel"
},
"imageBlock": {
"placeholder": "Klicken Sie, um ein Bild hinzuzufügen",
"placeholder": "Klicken, um ein Bild hinzuzufügen",
"upload": {
"label": "Hochladen",
"placeholder": "Klicken Sie, um das Bild hochzuladen"
"placeholder": "Klicken, um das Bild hochzuladen"
},
"url": {
"label": "Bild URL",
"placeholder": "Geben Sie die Bild-URL ein"
"placeholder": "Bild-URL eingeben"
},
"ai": {
"label": "Bild mit OpenAI erstellen",
"placeholder": "Bitte den Prompt für OpenAI eingeben, um ein Bild zu erstellen"
},
"stability_ai": {
"label": "Bild mit Stability AI erstellen",
"placeholder": "Bitte den Prompt für Stability AI eingeben, um ein Bild zu erstellen"
},
"support": "Die Bildgrößenbeschränkung beträgt 5 MB. Unterstützte Formate: JPEG, PNG, GIF, SVG",
"error": {
"invalidImage": "Ungültiges Bild",
"invalidImageSize": "Die Bildgröße muss weniger als 5 MB betragen",
"invalidImageSize": "Die Bildgröße muss kleiner als 5 MB sein",
"invalidImageFormat": "Das Bildformat wird nicht unterstützt. Unterstützte Formate: JPEG, PNG, GIF, SVG",
"invalidImageUrl": "Ungültige Bild-URL"
}
},
"embedLink": {
"label": "Eingebetteter Link",
"placeholder": "Bild-Link einfügen oder eintippen"
},
"unsplash": {
"label": "Unsplash"
},
"searchForAnImage": "Nach einem Bild suchen",
"pleaseInputYourOpenAIKey": "biitte den OpenAI Schlüssel in der Einstellungsseite eingeben",
"pleaseInputYourStabilityAIKey": "biitte den Stability AI Schlüssel in der Einstellungsseite eingeben",
"saveImageToGallery": "Bild speichern",
"failedToAddImageToGallery": "Das Bild konnte nicht zur Galerie hinzugefügt werden",
"successToAddImageToGallery": "Das Bild wurde zur Galerie hinzugefügt werden",
"unableToLoadImage": "Das Bild konnte nicht geladen werden"
},
"codeBlock": {
"language": {
@@ -646,23 +833,74 @@
}
},
"inlineLink": {
"placeholder": "Fügen Sie einen Link ein oder geben Sie ihn ein",
"placeholder": "Link einfügen oder eintippen",
"openInNewTab": "Im neuen Tab öffnen",
"copyLink": "Link kopieren",
"removeLink": "Link entfernen",
"url": {
"label": "URL verknüpfen",
"placeholder": "Geben Sie die Link-URL ein"
"placeholder": "Link-URL eingeben"
},
"title": {
"label": "Linktitel",
"placeholder": "Geben Sie den Linktitel ein"
"placeholder": "Linktitel eingeben"
}
},
"mention": {
"placeholder": "Eine Person, Seite oder Datum erwähnen...",
"page": {
"label": "Link zur Seite",
"tooltip": "Klicken, um die Seite zu öffnen"
}
},
"toolbar": {
"resetToDefaultFont": "Auf den Standard zurücksetzen"
},
"errorBlock": {
"theBlockIsNotSupported": "Die aktuelle Version unterstützt diesen Block nicht.",
"blockContentHasBeenCopied": "Der Blockinhalt wurde kopiert."
}
},
"board": {
"column": {
"createNewCard": "Neu"
"createNewCard": "Neu",
"renameGroupTooltip": "Drücken, um die Gruppe umzubenennen",
"createNewColumn": "Eine neue Gruppe hinzufügen",
"addToColumnTopTooltip": "Eine neue Karte am oberen Ende hinzufügen",
"addToColumnBottomTooltip": "Eine neue Karte am unteren Ende hinzufügen",
"renameColumn": "Umbenennen",
"hideColumn": "Verstecken",
"groupActions": "Gruppenaktion",
"newGroup": "Neue Gruppe",
"deleteColumn": "Löschen",
"deleteColumnConfirmation": "Das wird diese Gruppe und alle enthaltenen Karten löschen.\nSicher, dass Sie fortsetzen möchte?"
},
"hiddenGroupSection": {
"sectionTitle": "Versteckte Gruppen",
"collapseTooltip": "Verstecke die versteckten Gruppen",
"expandTooltip": "Zeige die versteckten Gruppen"
},
"cardDetail": "Kartendetail",
"cardActions": "Kartenaktionen",
"cardDuplicated": "Karte wurde dupliziert",
"cardDeleted": "Karte wurde gelöscht",
"showOnCard": "Zeige das Kartendetail",
"setting": "Einstellung",
"propertyName": "Eigenschaftname",
"menuName": "Board",
"referencedBoardPrefix": "Sicht von"
"showUngrouped": "Zeige nichtgruppierte Elemente",
"ungroupedButtonText": "Nichtgruppiert",
"ungroupedButtonTooltip": "Enthält Karten, die keiner Gruppe zugeordnet sind",
"ungroupedItemsTitle": "Klicke, um dem Board hinzuzufügen",
"groupBy": "Gruppiert nach",
"referencedBoardPrefix": "Sicht von",
"notesTooltip": "Notizen vorhanden",
"mobile": {
"editURL": "Bearbeite URL",
"unhideGroup": "Zeige die Gruppe",
"unhideGroupContent": "Sicher, dass diese Gruppe auf dem Board angezeigt werden soll?",
"faildToLoad": "Board Sicht konnte nicht geladen werden"
}
},
"calendar": {
"menuName": "Kalender",
+70 -55
View File
@@ -125,7 +125,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"reqwest",
@@ -204,7 +204,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -215,7 +215,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -413,7 +413,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -670,7 +670,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
@@ -736,7 +736,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -745,6 +745,7 @@ dependencies = [
"parking_lot",
"serde",
"serde_json",
"serde_repr",
"thiserror",
"tokio",
"tokio-stream",
@@ -755,7 +756,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -784,7 +785,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"collab",
@@ -802,7 +803,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"bytes",
@@ -816,7 +817,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"chrono",
@@ -853,7 +854,7 @@ dependencies = [
[[package]]
name = "collab-persistence"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -874,7 +875,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"async-trait",
@@ -900,7 +901,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7d7f53250f7a8297c69e2cdc72e441f5469eaf11#7d7f53250f7a8297c69e2cdc72e441f5469eaf11"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b036feb396aa6a1dbbab9589bd032e29db8ab024#b036feb396aa6a1dbbab9589bd032e29db8ab024"
dependencies = [
"anyhow",
"collab",
@@ -1132,7 +1133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -1249,10 +1250,11 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
"bincode",
"chrono",
"collab-entity",
"serde",
@@ -1365,7 +1367,7 @@ dependencies = [
"diesel_table_macro_syntax",
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -1385,7 +1387,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
dependencies = [
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -1532,6 +1534,7 @@ dependencies = [
"anyhow",
"assert-json-diff",
"bytes",
"chrono",
"collab",
"collab-database",
"collab-document",
@@ -2300,7 +2303,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -2450,7 +2453,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"futures-util",
@@ -2466,7 +2469,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
@@ -2827,7 +2830,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"reqwest",
@@ -3392,7 +3395,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -3572,7 +3575,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -3700,7 +3703,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -3747,7 +3750,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -3837,7 +3840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8832c0f9be7e3cae60727e6256cfd2cd3c3e2b6cd5dad4190ecb2fd658c9030b"
dependencies = [
"proc-macro2",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -3881,9 +3884,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.66"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db"
dependencies = [
"unicode-ident",
]
@@ -3915,7 +3918,7 @@ dependencies = [
"prost",
"prost-types",
"regex",
"syn 2.0.31",
"syn 2.0.46",
"tempfile",
"which",
]
@@ -3930,7 +3933,7 @@ dependencies = [
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -4099,9 +4102,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -4266,7 +4269,7 @@ dependencies = [
[[package]]
name = "realtime-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"bincode",
@@ -4288,7 +4291,7 @@ dependencies = [
[[package]]
name = "realtime-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"bincode",
@@ -4838,7 +4841,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -4854,13 +4857,13 @@ dependencies = [
[[package]]
name = "serde_repr"
version = "0.1.16"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -4946,7 +4949,7 @@ dependencies = [
[[package]]
name = "shared_entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"app-error",
@@ -5262,7 +5265,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -5284,9 +5287,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.31"
version = "2.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e"
dependencies = [
"proc-macro2",
"quote",
@@ -5397,7 +5400,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -5502,7 +5505,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -5718,11 +5721,12 @@ dependencies = [
[[package]]
name = "tracing-appender"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
dependencies = [
"crossbeam-channel",
"thiserror",
"time",
"tracing-subscriber",
]
@@ -5735,7 +5739,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
@@ -5752,7 +5756,7 @@ dependencies = [
"time",
"tracing",
"tracing-core",
"tracing-log",
"tracing-log 0.1.3",
"tracing-subscriber",
]
@@ -5777,6 +5781,17 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-serde"
version = "0.1.3"
@@ -5789,9 +5804,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.17"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"matchers",
"nu-ansi-term",
@@ -5804,7 +5819,7 @@ dependencies = [
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
"tracing-log 0.2.0",
"tracing-serde",
]
@@ -6127,7 +6142,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
"wasm-bindgen-shared",
]
@@ -6161,7 +6176,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -6351,7 +6366,7 @@ dependencies = [
[[package]]
name = "workspace-template"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a455c9de8e6448cec956da5a00ba5cc136ed7274#a455c9de8e6448cec956da5a00ba5cc136ed7274"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40daff472d026d155fc703aacce899b1c5ab98ea#40daff472d026d155fc703aacce899b1c5ab98ea"
dependencies = [
"anyhow",
"async-trait",
@@ -6409,7 +6424,7 @@ checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.31",
"syn 2.0.46",
]
[[package]]
+9 -9
View File
@@ -107,7 +107,7 @@ incremental = false
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a455c9de8e6448cec956da5a00ba5cc136ed7274" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "40daff472d026d155fc703aacce899b1c5ab98ea" }
# Please use the following script to update collab.
# Working directory: frontend
#
@@ -117,11 +117,11 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a45
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7d7f53250f7a8297c69e2cdc72e441f5469eaf11" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b036feb396aa6a1dbbab9589bd032e29db8ab024" }
@@ -48,6 +48,7 @@ tempdir = "0.3.7"
uuid.workspace = true
assert-json-diff = "2.0.2"
tokio-postgres = { version = "0.7.8" }
chrono = "0.4.31"
zip = "0.6.6"
[features]
@@ -64,17 +64,6 @@ impl EventIntegrationTest {
.items
}
pub async fn get_views(&self, parent_view_id: &str) -> ViewPB {
EventBuilder::new(self.clone())
.event(FolderEvent::GetView)
.payload(ViewIdPB {
value: parent_view_id.to_string(),
})
.async_send()
.await
.parse::<ViewPB>()
}
pub async fn get_trash(&self) -> RepeatedTrashPB {
EventBuilder::new(self.clone())
.event(FolderEvent::ListTrashItems)
+6 -19
View File
@@ -53,10 +53,8 @@ impl EventIntegrationTest {
let path = path_buf.to_str().unwrap().to_string();
let device_id = uuid::Uuid::new_v4().to_string();
let level = "info";
std::env::set_var("RUST_LOG", level);
let config = AppFlowyCoreConfig::new(path.clone(), path, device_id, name).log_filter(
level,
"trace",
vec![
"flowy_test".to_string(),
"tokio".to_string(),
@@ -79,27 +77,16 @@ impl EventIntegrationTest {
}
}
pub fn get_appflowy_cloud_server(&self) -> Arc<dyn AppFlowyServer> {
self
.appflowy_core
.server_provider
.get_appflowy_cloud_server()
.unwrap()
pub fn get_server(&self) -> Arc<dyn AppFlowyServer> {
self.appflowy_core.server_provider.get_server().unwrap()
}
pub async fn wait_ws_connected(&self) {
if self
.get_appflowy_cloud_server()
.get_ws_state()
.is_connected()
{
if self.get_server().get_ws_state().is_connected() {
return;
}
let mut ws_state = self
.get_appflowy_cloud_server()
.subscribe_ws_state()
.unwrap();
let mut ws_state = self.get_server().subscribe_ws_state().unwrap();
loop {
select! {
_ = sleep(Duration::from_secs(20)) => {
@@ -121,7 +108,7 @@ impl EventIntegrationTest {
oid: &str,
collay_type: CollabType,
) -> Result<CollabDocState, FlowyError> {
let server = self.server_provider.get_appflowy_cloud_server().unwrap();
let server = self.server_provider.get_server().unwrap();
let workspace_id = self.get_current_workspace().await.id;
let uid = self.get_user_profile().await?.id;
let doc_state = server
@@ -24,12 +24,12 @@ async fn reading_039_anon_user_data_test() {
);
assert_eq!(first_level_views[0].name, "Document1".to_string());
let second_level_views = test.get_views(&first_level_views[0].id).await.child_views;
let second_level_views = test.get_view(&first_level_views[0].id).await.child_views;
assert_eq!(second_level_views.len(), 1);
assert_eq!(second_level_views[0].name, "Document2".to_string());
// In the 039_local, there is only one view of the workspaces child
let third_level_views = test.get_views(&second_level_views[0].id).await.child_views;
let third_level_views = test.get_view(&second_level_views[0].id).await.child_views;
assert_eq!(third_level_views.len(), 2);
assert_eq!(third_level_views[0].name, "Grid1".to_string());
assert_eq!(third_level_views[1].name, "Grid2".to_string());
@@ -62,11 +62,11 @@ async fn migrate_anon_user_data_to_af_cloud_test() {
let anon_first_level_views = test.get_all_workspace_views().await;
let anon_second_level_views = test
.get_views(&anon_first_level_views[0].id)
.get_view(&anon_first_level_views[0].id)
.await
.child_views;
let anon_third_level_views = test
.get_views(&anon_second_level_views[0].id)
.get_view(&anon_second_level_views[0].id)
.await
.child_views;
@@ -82,12 +82,12 @@ async fn migrate_anon_user_data_to_af_cloud_test() {
println!("user first level views: {:?}", user_first_level_views);
let user_second_level_views = test
.get_views(&user_first_level_views[0].id)
.get_view(&user_first_level_views[0].id)
.await
.child_views;
println!("user second level views: {:?}", user_second_level_views);
let user_third_level_views = test
.get_views(&user_second_level_views[0].id)
.get_view(&user_second_level_views[0].id)
.await
.child_views;
println!("user third level views: {:?}", user_third_level_views);
@@ -1,5 +1,6 @@
use crate::util::unzip_history_user_db;
use assert_json_diff::assert_json_include;
use collab_database::rows::database_row_document_id_from_row_id;
use collab_entity::CollabType;
use event_integration::user_event::user_localhost_af_cloud;
use event_integration::{document_data_from_document_doc_state, EventIntegrationTest};
@@ -45,22 +46,33 @@ async fn import_appflowy_data_folder_into_new_view_test() {
assert_eq!(views.len(), 2);
assert_eq!(views[1].name, import_container_name);
let local_child_views = test.get_views(&views[1].id).await.child_views;
// the 040_local should be an empty document, so try to get the document data
let _ = test.get_document_data(&views[1].id).await;
let local_child_views = test.get_view(&views[1].id).await.child_views;
assert_eq!(local_child_views.len(), 1);
assert_eq!(local_child_views[0].name, "Document1");
let document1_child_views = test.get_views(&local_child_views[0].id).await.child_views;
let document1_child_views = test.get_view(&local_child_views[0].id).await.child_views;
assert_eq!(document1_child_views.len(), 1);
assert_eq!(document1_child_views[0].name, "Document2");
let document2_child_views = test
.get_views(&document1_child_views[0].id)
.get_view(&document1_child_views[0].id)
.await
.child_views;
assert_eq!(document2_child_views.len(), 2);
assert_eq!(document2_child_views[0].name, "Grid1");
assert_eq!(document2_child_views[1].name, "Grid2");
let rows = test.get_database(&document2_child_views[1].id).await.rows;
assert_eq!(rows.len(), 3);
// In the 040_local, only the first row has a document with content
let row_document_id = database_row_document_id_from_row_id(&rows[0].id);
let row_document_data = test.get_document_data(&row_document_id).await;
assert_json_include!(actual: json!(row_document_data), expected: expected_row_doc_json());
drop(cleaner);
}
@@ -97,12 +109,12 @@ async fn import_appflowy_data_folder_into_current_workspace_test() {
assert_eq!(views.len(), 2);
assert_eq!(views[1].name, "Document1");
let document_1_child_views = test.get_views(&views[1].id).await.child_views;
let document_1_child_views = test.get_view(&views[1].id).await.child_views;
assert_eq!(document_1_child_views.len(), 1);
assert_eq!(document_1_child_views[0].name, "Document2");
let document2_child_views = test
.get_views(&document_1_child_views[0].id)
.get_view(&document_1_child_views[0].id)
.await
.child_views;
assert_eq!(document2_child_views.len(), 2);
@@ -216,14 +228,12 @@ async fn assert_040_local_2_import_content(test: &EventIntegrationTest, view_id:
// Doc3_grid_1
// Doc3_grid_2
// Doc3_calendar_1
let _local_2_child_views = test.get_views(view_id).await.child_views;
let _local_2_child_views = test.get_view(view_id).await.child_views;
assert_eq!(_local_2_child_views.len(), 1);
assert_eq!(_local_2_child_views[0].name, "Getting started");
let local_2_getting_started_child_views = test
.get_views(&_local_2_child_views[0].id)
.await
.child_views;
let local_2_getting_started_child_views =
test.get_view(&_local_2_child_views[0].id).await.child_views;
// Check doc 1 local content
let doc_1 = local_2_getting_started_child_views[0].clone();
@@ -258,7 +268,7 @@ async fn assert_040_local_2_import_content(test: &EventIntegrationTest, view_id:
assert_eq!(local_2_getting_started_child_views[3].name, "Doc3");
let doc_3_child_views = test
.get_views(&local_2_getting_started_child_views[3].id)
.get_view(&local_2_getting_started_child_views[3].id)
.await
.child_views;
assert_eq!(doc_3_child_views.len(), 3);
@@ -372,3 +382,46 @@ fn expected_doc_2_json() -> Value {
"page_id": "ZVogdaK9yO"
})
}
fn expected_row_doc_json() -> Value {
json!( {
"blocks": {
"eSBQHZ28e0": {
"children": "RbLAaE9UDJ",
"data": {},
"external_id": null,
"external_type": null,
"id": "eSBQHZ28e0",
"parent": "",
"ty": "page"
},
"eUIL6qjgj3": {
"children": "fUnGRcvPEA",
"data": {
"delta": [
{
"insert": "document in database row"
}
]
},
"external_id": "-DliEUjHr2",
"external_type": "text",
"id": "eUIL6qjgj3",
"parent": "eSBQHZ28e0",
"ty": "paragraph"
}
},
"meta": {
"children_map": {
"RbLAaE9UDJ": [
"eUIL6qjgj3"
],
"fUnGRcvPEA": []
},
"text_map": {
"-DliEUjHr2": "[{\"insert\":\"document in database row\"}]"
}
},
"page_id": "eSBQHZ28e0"
})
}
@@ -1,6 +1,7 @@
use event_integration::EventIntegrationTest;
use flowy_core::DEFAULT_NAME;
use flowy_folder::entities::ViewLayoutPB;
use std::time::Duration;
use crate::util::unzip_history_user_db;
@@ -26,7 +27,7 @@ async fn migrate_020_historical_empty_document_test() {
assert!(!data.meta.children_map.is_empty());
// Check the child views of the parent view
let child_views = test.get_views(&parent_view.id).await.child_views;
let child_views = test.get_view(&parent_view.id).await.child_views;
assert_eq!(child_views.len(), 4);
assert_eq!(child_views[0].layout, ViewLayoutPB::Document);
assert_eq!(child_views[1].layout, ViewLayoutPB::Grid);
@@ -55,8 +56,127 @@ async fn migrate_036_fav_v1_workspace_array_test() {
assert_eq!(views[0].name, "root page");
assert_eq!(views[1].name, "⭐\u{fe0f} Getting started");
let views = test.get_views(&views[1].id).await;
let views = test.get_view(&views[1].id).await;
assert_eq!(views.child_views.len(), 3);
assert!(views.child_views[2].is_favorite);
drop(cleaner);
}
#[tokio::test]
async fn migrate_038_trash_test() {
// Used to test migration: WorkspaceTrashMapToSectionMigration
let (cleaner, user_db_path) = unzip_history_user_db("./tests/asset", "038_local").unwrap();
// Getting started
// Document1
// Document2(deleted)
// Document3(deleted)
// Document
// Document4(deleted)
// Document5
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
let views = test.get_all_workspace_views().await;
assert_eq!(views.len(), 2);
assert_eq!(views[0].name, "Getting started");
assert_eq!(views[1].name, "Documents");
let get_started_child_views = test.get_view(&views[0].id).await.child_views;
assert_eq!(get_started_child_views.len(), 1);
assert_eq!(get_started_child_views[0].name, "Document1");
let get_started_child_views = test.get_view(&views[1].id).await.child_views;
assert_eq!(get_started_child_views.len(), 1);
assert_eq!(get_started_child_views[0].name, "Document5");
let trash_items = test.get_trash().await.items;
assert_eq!(trash_items.len(), 3);
assert_eq!(trash_items[0].name, "Document3");
assert_eq!(trash_items[1].name, "Document2");
assert_eq!(trash_items[2].name, "Document4");
drop(cleaner);
}
#[tokio::test]
async fn migrate_038_trash_test2() {
// Used to test migration: WorkspaceTrashMapToSectionMigration
let (cleaner, user_db_path) =
unzip_history_user_db("./tests/asset", "038_document_with_grid").unwrap();
// Getting started
// document
// grid
// board
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
let views = test.get_all_workspace_views().await;
assert_eq!(views.len(), 1);
assert_eq!(views[0].name, "Getting started");
let views = test.get_view(&views[0].id).await.child_views;
assert_eq!(views[0].name, "document");
let views = test.get_view(&views[0].id).await.child_views;
assert_eq!(views[0].name, "grid");
let views = test.get_view(&views[0].id).await.child_views;
assert_eq!(views[0].name, "board");
drop(cleaner);
}
#[tokio::test]
async fn collab_db_backup_test() {
// Used to test migration: WorkspaceTrashMapToSectionMigration
let (cleaner, user_db_path) = unzip_history_user_db("./tests/asset", "038_local").unwrap();
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
let uid = test.get_user_profile().await.unwrap().id;
let backups = test.user_manager.get_collab_backup_list(uid);
assert_eq!(backups.len(), 1);
assert_eq!(
backups[0],
format!("collab_db_{}", chrono::Local::now().format("%Y%m%d"))
);
drop(cleaner);
}
#[tokio::test]
async fn delete_outdated_collab_db_backup_test() {
// Used to test migration: WorkspaceTrashMapToSectionMigration
let (cleaner, user_db_path) =
unzip_history_user_db("./tests/asset", "040_collab_backups").unwrap();
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
let uid = test.get_user_profile().await.unwrap().id;
// saving the backup is a background task, so we need to wait for it to finish
// 2 seconds should be enough for the background task to finish
tokio::time::sleep(Duration::from_secs(2)).await;
let backups = test.user_manager.get_collab_backup_list(uid);
if backups.len() != 10 {
dbg!("backups: {:?}", backups.clone());
}
assert_eq!(backups.len(), 10);
assert_eq!(backups[0], "collab_db_0.4.0_20231202");
assert_eq!(backups[1], "collab_db_0.4.0_20231203");
assert_eq!(backups[2], "collab_db_0.4.0_20231204");
assert_eq!(backups[3], "collab_db_0.4.0_20231205");
assert_eq!(backups[4], "collab_db_0.4.0_20231206");
assert_eq!(backups[5], "collab_db_0.4.0_20231207");
assert_eq!(backups[6], "collab_db_0.4.0_20231208");
assert_eq!(backups[7], "collab_db_0.4.0_20231209");
assert_eq!(backups[8], "collab_db_0.4.0_20231210");
assert_eq!(
backups[9],
format!("collab_db_{}", chrono::Local::now().format("%Y%m%d"))
);
drop(cleaner);
}
@@ -27,7 +27,7 @@ use flowy_user::entities::{AuthenticatorPB, UpdateUserProfilePayloadPB};
use flowy_user::errors::FlowyError;
use flowy_user::event_map::UserEvent::*;
use flowy_user_deps::cloud::{UserCloudService, UserCloudServiceProvider};
use flowy_user_deps::cloud::UserCloudService;
use flowy_user_deps::entities::Authenticator;
pub fn get_supabase_config() -> Option<SupabaseConfiguration> {
+3 -3
View File
@@ -41,7 +41,7 @@ impl fmt::Debug for AppFlowyCoreConfig {
}
}
fn migrate_local_version_data_folder(root: &str, url: &str) -> String {
fn make_user_data_folder(root: &str, url: &str) -> String {
// Isolate the user data folder by using the base url of AppFlowy cloud. This is to avoid
// the user data folder being shared by different AppFlowy cloud.
let storage_path = if !url.is_empty() {
@@ -82,10 +82,10 @@ impl AppFlowyCoreConfig {
let supabase_config = SupabaseConfiguration::from_env().ok();
match &supabase_config {
None => custom_application_path,
Some(config) => migrate_local_version_data_folder(&custom_application_path, &config.url),
Some(config) => make_user_data_folder(&custom_application_path, &config.url),
}
},
Some(config) => migrate_local_version_data_folder(&custom_application_path, &config.base_url),
Some(config) => make_user_data_folder(&custom_application_path, &config.base_url),
};
AppFlowyCoreConfig {
@@ -1,6 +1,6 @@
use std::sync::{Arc, Weak};
use collab::core::collab_plugin::EncodedCollabV1;
use collab::core::collab_plugin::EncodedCollab;
use collab_plugins::local_storage::rocksdb::RocksdbBackup;
use diesel::SqliteConnection;
@@ -22,12 +22,7 @@ impl RocksdbBackupImpl {
}
impl RocksdbBackup for RocksdbBackupImpl {
fn save_doc(
&self,
uid: i64,
object_id: &str,
data: EncodedCollabV1,
) -> Result<(), anyhow::Error> {
fn save_doc(&self, uid: i64, object_id: &str, data: EncodedCollab) -> Result<(), anyhow::Error> {
let row = RocksdbBackupRow {
object_id: object_id.to_string(),
timestamp: timestamp(),
@@ -40,7 +35,7 @@ impl RocksdbBackup for RocksdbBackupImpl {
Ok(())
}
fn get_doc(&self, uid: i64, object_id: &str) -> Result<EncodedCollabV1, anyhow::Error> {
fn get_doc(&self, uid: i64, object_id: &str) -> Result<EncodedCollab, anyhow::Error> {
let sql = dsl::rocksdb_backup
.filter(dsl::object_id.eq(object_id))
.into_boxed();
@@ -50,7 +45,7 @@ impl RocksdbBackup for RocksdbBackupImpl {
.get()
.map(|mut conn| sql.first::<RocksdbBackupRow>(&mut *conn))??;
Ok(EncodedCollabV1::decode_from_bytes(&row.data)?)
Ok(EncodedCollab::decode_from_bytes(&row.data)?)
}
}
@@ -238,8 +238,16 @@ impl FolderOperationHandler for DocumentFolderOperation {
let view_id = view_id.to_string();
let manager = self.0.clone();
FutureResult::new(async move {
manager.create_document(user_id, &view_id, None).await?;
Ok(())
match manager.create_document(user_id, &view_id, None).await {
Ok(_) => Ok(()),
Err(err) => {
if err.is_already_exists() {
Ok(())
} else {
Err(err)
}
},
}
})
}
@@ -368,8 +376,17 @@ impl FolderOperationHandler for DatabaseFolderOperation {
},
};
FutureResult::new(async move {
database_manager.create_database_with_params(data).await?;
Ok(())
let result = database_manager.create_database_with_params(data).await;
match result {
Ok(_) => Ok(()),
Err(err) => {
if err.is_already_exists() {
Ok(())
} else {
Err(err)
}
},
}
})
}
@@ -19,7 +19,7 @@ pub(crate) fn create_log_filter(level: String, with_crates: Vec<String>) -> Stri
.map(|crate_name| format!("{}={}", crate_name, level))
.collect::<Vec<String>>();
filters.push(format!("flowy_core={}", level));
filters.push(format!("flowy_folder2={}", level));
filters.push(format!("flowy_folder={}", level));
filters.push(format!("collab_sync={}", level));
filters.push(format!("collab_folder={}", level));
filters.push(format!("collab_persistence={}", level));
@@ -28,7 +28,7 @@ pub(crate) fn create_log_filter(level: String, with_crates: Vec<String>) -> Stri
filters.push(format!("collab_integrate={}", level));
filters.push(format!("collab={}", level));
filters.push(format!("flowy_user={}", level));
filters.push(format!("flowy_document2={}", level));
filters.push(format!("flowy_document={}", level));
filters.push(format!("flowy_database2={}", level));
filters.push(format!("flowy_server={}", level));
filters.push(format!("flowy_notification={}", "info"));
@@ -33,6 +33,12 @@ pub enum Server {
Supabase = 2,
}
impl Server {
pub fn is_local(&self) -> bool {
matches!(self, Server::Local)
}
}
impl Display for Server {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
@@ -49,7 +55,6 @@ impl Display for Server {
/// Each server implements the [AppFlowyServer] trait, which provides the [UserCloudService], etc.
pub struct ServerProvider {
config: AppFlowyCoreConfig,
server: RwLock<Server>,
providers: RwLock<HashMap<Server, Arc<dyn AppFlowyServer>>>,
pub(crate) encryption: RwLock<Arc<dyn AppFlowyEncryption>>,
#[allow(dead_code)]
@@ -57,7 +62,7 @@ pub struct ServerProvider {
pub(crate) user_enable_sync: RwLock<bool>,
/// The authenticator type of the user.
pub(crate) user_authenticator: RwLock<Authenticator>,
authenticator: RwLock<Authenticator>,
pub(crate) uid: Arc<RwLock<Option<i64>>>,
}
@@ -70,10 +75,9 @@ impl ServerProvider {
let encryption = EncryptionImpl::new(None);
Self {
config,
server: RwLock::new(server),
providers: RwLock::new(HashMap::new()),
user_enable_sync: RwLock::new(true),
user_authenticator: RwLock::new(Authenticator::Local),
authenticator: RwLock::new(Authenticator::from(server)),
encryption: RwLock::new(Arc::new(encryption)),
store_preferences,
uid: Default::default(),
@@ -81,30 +85,32 @@ impl ServerProvider {
}
pub fn get_server_type(&self) -> Server {
self.server.read().clone()
match &*self.authenticator.read() {
Authenticator::Local => Server::Local,
Authenticator::AppFlowyCloud => Server::AppFlowyCloud,
Authenticator::Supabase => Server::Supabase,
}
}
pub fn set_server_type(&self, server_type: Server) {
let old_server_type = self.server.read().clone();
if server_type != old_server_type {
pub fn set_authenticator(&self, authenticator: Authenticator) {
let old_server_type = self.get_server_type();
*self.authenticator.write() = authenticator;
let new_server_type = self.get_server_type();
if old_server_type != new_server_type {
self.providers.write().remove(&old_server_type);
}
*self.server.write() = server_type;
}
pub fn get_user_authenticator(&self) -> Authenticator {
self.user_authenticator.read().clone()
}
pub fn get_appflowy_cloud_server(&self) -> FlowyResult<Arc<dyn AppFlowyServer>> {
let server = self.get_server(&Server::AppFlowyCloud)?;
Ok(server)
pub fn get_authenticator(&self) -> Authenticator {
self.authenticator.read().clone()
}
/// Returns a [AppFlowyServer] trait implementation base on the provider_type.
pub fn get_server(&self, server_type: &Server) -> FlowyResult<Arc<dyn AppFlowyServer>> {
if let Some(provider) = self.providers.read().get(server_type) {
pub fn get_server(&self) -> FlowyResult<Arc<dyn AppFlowyServer>> {
let server_type = self.get_server_type();
if let Some(provider) = self.providers.read().get(&server_type) {
return Ok(provider.clone());
}
@@ -32,7 +32,7 @@ use crate::integrate::server::{Server, ServerProvider};
impl FileStorageService for ServerProvider {
fn create_object(&self, object: StorageObject) -> FutureResult<String, FlowyError> {
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
let storage = server?.file_storage().ok_or(FlowyError::internal())?;
storage.create_object(object).await
@@ -40,7 +40,7 @@ impl FileStorageService for ServerProvider {
}
fn delete_object_by_url(&self, object_url: String) -> FutureResult<(), FlowyError> {
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
let storage = server?.file_storage().ok_or(FlowyError::internal())?;
storage.delete_object_by_url(object_url).await
@@ -48,7 +48,7 @@ impl FileStorageService for ServerProvider {
}
fn get_object_by_url(&self, object_url: String) -> FutureResult<Bytes, FlowyError> {
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
let storage = server?.file_storage().ok_or(FlowyError::internal())?;
storage.get_object_by_url(object_url).await
@@ -58,42 +58,40 @@ impl FileStorageService for ServerProvider {
impl UserCloudServiceProvider for ServerProvider {
fn set_token(&self, token: &str) -> Result<(), FlowyError> {
let server = self.get_server(&self.get_server_type())?;
let server = self.get_server()?;
server.set_token(token)?;
Ok(())
}
fn subscribe_token_state(&self) -> Option<WatchStream<UserTokenState>> {
let server = self.get_server(&self.get_server_type()).ok()?;
let server = self.get_server().ok()?;
server.subscribe_token_state()
}
fn set_enable_sync(&self, uid: i64, enable_sync: bool) {
if let Ok(server) = self.get_server(&self.get_server_type()) {
if let Ok(server) = self.get_server() {
server.set_enable_sync(uid, enable_sync);
*self.user_enable_sync.write() = enable_sync;
*self.uid.write() = Some(uid);
}
}
fn set_user_authenticator(&self, authenticator: &Authenticator) {
debug!("set user authenticator: {:?}", authenticator);
*self.user_authenticator.write() = authenticator.clone();
}
/// When user login, the provider type is set by the [Authenticator] and save to disk for next use.
///
/// Each [Authenticator] has a corresponding [Server]. The [Server] is used
/// to create a new [AppFlowyServer] if it doesn't exist. Once the [Server] is set,
/// it will be used when user open the app again.
///
fn set_authenticator(&self, authenticator: Authenticator) {
let server_type: Server = authenticator.into();
self.set_server_type(server_type.clone());
fn set_user_authenticator(&self, authenticator: &Authenticator) {
self.set_authenticator(authenticator.clone());
}
fn get_user_authenticator(&self) -> Authenticator {
self.get_authenticator()
}
fn set_network_reachable(&self, reachable: bool) {
if let Ok(server) = self.get_server(&self.get_server_type()) {
if let Ok(server) = self.get_server() {
server.set_network_reachable(reachable);
}
}
@@ -103,16 +101,10 @@ impl UserCloudServiceProvider for ServerProvider {
self.encryption.write().set_secret(secret);
}
fn get_authenticator(&self) -> Authenticator {
let server_type = self.get_server_type();
Authenticator::from(server_type)
}
/// Returns the [UserCloudService] base on the current [Server].
/// Creates a new [AppFlowyServer] if it doesn't exist.
fn get_user_service(&self) -> Result<Arc<dyn UserCloudService>, FlowyError> {
let server_type = self.get_server_type();
let user_service = self.get_server(&server_type)?.user_service();
let user_service = self.get_server()?.user_service();
Ok(user_service)
}
@@ -131,19 +123,19 @@ impl UserCloudServiceProvider for ServerProvider {
impl FolderCloudService for ServerProvider {
fn create_workspace(&self, uid: i64, name: &str) -> FutureResult<Workspace, Error> {
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
let name = name.to_string();
FutureResult::new(async move { server?.folder_service().create_workspace(uid, &name).await })
}
fn open_workspace(&self, workspace_id: &str) -> FutureResult<(), Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move { server?.folder_service().open_workspace(&workspace_id).await })
}
fn get_all_workspace(&self) -> FutureResult<Vec<WorkspaceRecord>, Error> {
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move { server?.folder_service().get_all_workspace().await })
}
@@ -153,7 +145,7 @@ impl FolderCloudService for ServerProvider {
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
let workspace_id = workspace_id.to_string();
FutureResult::new(async move {
server?
@@ -169,7 +161,7 @@ impl FolderCloudService for ServerProvider {
limit: usize,
) -> FutureResult<Vec<FolderSnapshot>, Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
server?
.folder_service()
@@ -187,7 +179,7 @@ impl FolderCloudService for ServerProvider {
) -> FutureResult<CollabDocState, Error> {
let object_id = object_id.to_string();
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
server?
.folder_service()
@@ -202,7 +194,7 @@ impl FolderCloudService for ServerProvider {
objects: Vec<FolderCollabParams>,
) -> FutureResult<(), Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
server?
.folder_service()
@@ -213,7 +205,7 @@ impl FolderCloudService for ServerProvider {
fn service_name(&self) -> String {
self
.get_server(&self.get_server_type())
.get_server()
.map(|provider| provider.folder_service().service_name())
.unwrap_or_default()
}
@@ -227,7 +219,7 @@ impl DatabaseCloudService for ServerProvider {
workspace_id: &str,
) -> FutureResult<CollabDocState, Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
let database_id = object_id.to_string();
FutureResult::new(async move {
server?
@@ -244,7 +236,7 @@ impl DatabaseCloudService for ServerProvider {
workspace_id: &str,
) -> FutureResult<CollabDocStateByOid, Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
server?
.database_service()
@@ -258,7 +250,7 @@ impl DatabaseCloudService for ServerProvider {
object_id: &str,
limit: usize,
) -> FutureResult<Vec<DatabaseSnapshot>, Error> {
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
let database_id = object_id.to_string();
FutureResult::new(async move {
server?
@@ -277,7 +269,7 @@ impl DocumentCloudService for ServerProvider {
) -> FutureResult<CollabDocState, FlowyError> {
let workspace_id = workspace_id.to_string();
let document_id = document_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
FutureResult::new(async move {
server?
.document_service()
@@ -293,7 +285,7 @@ impl DocumentCloudService for ServerProvider {
workspace_id: &str,
) -> FutureResult<Vec<DocumentSnapshot>, Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
let document_id = document_id.to_string();
FutureResult::new(async move {
server?
@@ -309,7 +301,7 @@ impl DocumentCloudService for ServerProvider {
workspace_id: &str,
) -> FutureResult<Option<DocumentData>, Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server(&self.get_server_type());
let server = self.get_server();
let document_id = document_id.to_string();
FutureResult::new(async move {
server?
@@ -328,7 +320,7 @@ impl CollabCloudPluginProvider for ServerProvider {
#[instrument(level = "debug", skip(self, context), fields(server_type = %self.get_server_type()))]
fn get_plugins(&self, context: CollabPluginProviderContext) -> Fut<Vec<Arc<dyn CollabPlugin>>> {
// If the user is local, we don't need to create a sync plugin.
if self.user_authenticator.read().is_local() {
if self.get_server_type().is_local() {
debug!(
"User authenticator is local, skip create sync plugin for: {}",
context
@@ -343,7 +335,7 @@ impl CollabCloudPluginProvider for ServerProvider {
collab_object,
local_collab,
} => {
if let Ok(server) = self.get_server(&Server::AppFlowyCloud) {
if let Ok(server) = self.get_server() {
to_fut(async move {
let mut plugins: Vec<Arc<dyn CollabPlugin>> = vec![];
@@ -394,7 +386,7 @@ impl CollabCloudPluginProvider for ServerProvider {
} => {
let mut plugins: Vec<Arc<dyn CollabPlugin>> = vec![];
if let Some(remote_collab_storage) = self
.get_server(&Server::Supabase)
.get_server()
.ok()
.and_then(|provider| provider.collab_storage(&collab_object))
{
+32 -31
View File
@@ -3,12 +3,12 @@ use std::sync::Arc;
use std::sync::Weak;
use collab::core::collab::{CollabDocState, MutexCollab};
use collab::core::collab_plugin::EncodedCollabV1;
use collab::core::collab_plugin::EncodedCollab;
use collab::core::origin::CollabOrigin;
use collab::preclude::Collab;
use collab_document::blocks::DocumentData;
use collab_document::document::Document;
use collab_document::document_data::{default_document_collab_data, default_document_data};
use collab_document::document_data::default_document_data;
use collab_document::YrsDocAction;
use collab_entity::CollabType;
use lru::LruCache;
@@ -86,25 +86,45 @@ impl DocumentManager {
///
/// if the document already exists, return the existing document.
/// if the data is None, will create a document with default data.
#[instrument(level = "info", skip(self, data))]
pub async fn create_document(
&self,
uid: i64,
doc_id: &str,
data: Option<DocumentData>,
) -> FlowyResult<()> {
tracing::trace!("create a document: {:?}", doc_id);
if self.is_doc_exist(doc_id).unwrap_or(false) {
Err(FlowyError::new(
ErrorCode::RecordAlreadyExists,
format!("document {} already exists", doc_id),
))
} else {
let encoded_collab_v1 =
doc_state_from_document_data(doc_id, data.unwrap_or_else(default_document_data))?;
let collab = self
.collab_for_document(uid, doc_id, encoded_collab_v1.doc_state.to_vec(), false)
.await?;
collab.lock().flush();
let result: Result<CollabDocState, FlowyError> = self
.cloud_service
.get_document_doc_state(doc_id, &self.user.workspace_id()?)
.await;
match result {
Ok(data) => {
let collab = self.collab_for_document(uid, doc_id, data, false).await?;
collab.lock().flush();
},
Err(err) => {
if err.is_record_not_found() {
let doc_state =
doc_state_from_document_data(doc_id, data.unwrap_or_else(default_document_data))?
.doc_state
.to_vec();
let collab = self
.collab_for_document(uid, doc_id, doc_state, false)
.await?;
collab.lock().flush();
} else {
return Err(err);
}
},
}
Ok(())
}
}
@@ -119,29 +139,10 @@ impl DocumentManager {
let mut doc_state = vec![];
if !self.is_doc_exist(doc_id)? {
// Try to get the document from the cloud service
let result: Result<CollabDocState, FlowyError> = self
doc_state = self
.cloud_service
.get_document_doc_state(doc_id, &self.user.workspace_id()?)
.await;
doc_state = match result {
Ok(data) => data,
Err(err) => {
if err.is_record_not_found() {
// The document's ID exists in the cloud, but its content does not.
// This occurs when user A's document hasn't finished syncing and user B tries to open it.
// As a result, a blank document is created for user B.
event!(
tracing::Level::INFO,
"can't find the document in the cloud, doc_id: {}",
doc_id
);
default_document_collab_data(doc_id).doc_state.to_vec()
} else {
return Err(err);
}
},
}
.await?;
}
let uid = self.user.user_id()?;
@@ -273,7 +274,7 @@ impl DocumentManager {
fn doc_state_from_document_data(
doc_id: &str,
data: DocumentData,
) -> Result<EncodedCollabV1, FlowyError> {
) -> Result<EncodedCollab, FlowyError> {
let collab = Arc::new(MutexCollab::from_collab(Collab::new_with_origin(
CollabOrigin::Empty,
doc_id,
@@ -21,7 +21,7 @@ use collab_integrate::RocksCollabDB;
use flowy_document::document::MutexDocument;
use flowy_document::manager::{DocumentManager, DocumentUser};
use flowy_document_deps::cloud::*;
use flowy_error::FlowyError;
use flowy_error::{ErrorCode, FlowyError};
use flowy_storage::{FileStorageService, StorageObject};
use lib_infra::async_trait::async_trait;
use lib_infra::future::{to_fut, Fut, FutureResult};
@@ -135,10 +135,16 @@ pub struct LocalTestDocumentCloudServiceImpl();
impl DocumentCloudService for LocalTestDocumentCloudServiceImpl {
fn get_document_doc_state(
&self,
_document_id: &str,
document_id: &str,
_workspace_id: &str,
) -> FutureResult<CollabDocState, FlowyError> {
FutureResult::new(async move { Ok(vec![]) })
let document_id = document_id.to_string();
FutureResult::new(async move {
Err(FlowyError::new(
ErrorCode::RecordNotFound,
format!("Document {} not found", document_id),
))
})
}
fn get_document_snapshots(
@@ -55,6 +55,10 @@ impl FlowyError {
self.code == ErrorCode::RecordNotFound
}
pub fn is_already_exists(&self) -> bool {
self.code == ErrorCode::RecordAlreadyExists
}
pub fn is_unauthorized(&self) -> bool {
self.code == ErrorCode::UserUnauthorized || self.code == ErrorCode::RecordNotFound
}
@@ -398,11 +398,13 @@ impl FolderManager {
params: CreateViewParams,
) -> FlowyResult<View> {
let view_layout: ViewLayout = params.layout.clone().into();
// TODO(nathan): remove orphan view. Just use for create document in row
let handler = self.get_handler(&view_layout)?;
let user_id = self.user.user_id()?;
handler
.create_built_in_view(user_id, &params.view_id, &params.name, view_layout.clone())
.await?;
let view = create_view(self.user.user_id()?, params, view_layout);
self.with_folder(
|| (),
@@ -3,7 +3,7 @@ use client_api::entity::QueryCollabResult::{Failed, Success};
use client_api::entity::{QueryCollab, QueryCollabParams};
use client_api::error::ErrorCode::RecordNotFound;
use collab::core::collab::CollabDocState;
use collab::core::collab_plugin::EncodedCollabV1;
use collab::core::collab_plugin::EncodedCollab;
use collab_entity::CollabType;
use tracing::error;
@@ -72,7 +72,7 @@ where
.into_iter()
.flat_map(|(object_id, result)| match result {
Success { encode_collab_v1 } => {
match EncodedCollabV1::decode_from_bytes(&encode_collab_v1) {
match EncodedCollab::decode_from_bytes(&encode_collab_v1) {
Ok(encode) => Some((object_id, encode.doc_state.to_vec())),
Err(err) => {
error!("Failed to decode collab: {}", err);
@@ -264,7 +264,7 @@ where
.into_iter()
.map(|object| CollabParams {
object_id: object.object_id,
encoded_collab_v1: object.encoded_collab_v1,
encoded_collab_v1: object.encoded_collab,
collab_type: object.collab_type,
override_if_exist: false,
})
@@ -2,7 +2,7 @@ use anyhow::Error;
use collab::core::collab::CollabDocState;
use flowy_document_deps::cloud::*;
use flowy_error::FlowyError;
use flowy_error::{ErrorCode, FlowyError};
use lib_infra::future::FutureResult;
pub(crate) struct LocalServerDocumentCloudServiceImpl();
@@ -10,10 +10,16 @@ pub(crate) struct LocalServerDocumentCloudServiceImpl();
impl DocumentCloudService for LocalServerDocumentCloudServiceImpl {
fn get_document_doc_state(
&self,
_document_id: &str,
document_id: &str,
_workspace_id: &str,
) -> FutureResult<CollabDocState, FlowyError> {
FutureResult::new(async move { Ok(vec![]) })
let document_id = document_id.to_string();
FutureResult::new(async move {
Err(FlowyError::new(
ErrorCode::RecordNotFound,
format!("Document {} not found", document_id),
))
})
}
fn get_document_snapshots(
+5 -12
View File
@@ -86,16 +86,15 @@ pub trait UserCloudServiceProvider: Send + Sync + 'static {
/// * `enable_sync`: A boolean indicating whether synchronization should be enabled or disabled.
fn set_enable_sync(&self, uid: i64, enable_sync: bool);
/// Sets the authentication type for a user. The authentication type is the type when user sign in or sign up.
fn set_user_authenticator(&self, authenticator: &Authenticator);
/// Sets the authenticator when user sign in or sign up.
///
/// # Arguments
/// * `authenticator`: An `Authenticator` object.
fn set_authenticator(&self, authenticator: Authenticator);
fn set_user_authenticator(&self, authenticator: &Authenticator);
/// Sets the network reachability status.
fn get_user_authenticator(&self) -> Authenticator;
/// Sets the network reachability statset_user_authenticatorus.
///
/// # Arguments
/// * `reachable`: A boolean indicating whether the network is reachable.
@@ -107,12 +106,6 @@ pub trait UserCloudServiceProvider: Send + Sync + 'static {
/// * `secret`: A `String` representing the encryption secret.
fn set_encrypt_secret(&self, secret: String);
/// Retrieves the current authenticator.
///
/// # Returns
/// The current `Authenticator` object.
fn get_authenticator(&self) -> Authenticator;
/// Retrieves the user-specific cloud service.
///
/// # Returns
@@ -247,6 +240,6 @@ pub fn uuid_from_map(map: &HashMap<String, String>) -> Result<Uuid, Error> {
#[derive(Debug)]
pub struct UserCollabParams {
pub object_id: String,
pub encoded_collab_v1: Vec<u8>,
pub encoded_collab: Vec<u8>,
pub collab_type: CollabType,
}
@@ -43,8 +43,16 @@ pub async fn sign_in_with_email_password_handler(
let params: SignInParams = data.into_inner().try_into()?;
let auth_type = params.auth_type.clone();
let user_profile: UserProfilePB = manager.sign_in(params, auth_type).await?.into();
data_result_ok(user_profile)
let old_authenticator = manager.cloud_services.get_user_authenticator();
match manager.sign_in(params, auth_type).await {
Ok(profile) => data_result_ok(UserProfilePB::from(profile)),
Err(err) => {
manager
.cloud_services
.set_user_authenticator(&old_authenticator);
return Err(err);
},
}
}
#[tracing::instrument(
@@ -63,10 +71,18 @@ pub async fn sign_up(
) -> DataResult<UserProfilePB, FlowyError> {
let manager = upgrade_manager(manager)?;
let params: SignUpParams = data.into_inner().try_into()?;
let auth_type = params.auth_type.clone();
let authenticator = params.auth_type.clone();
let user_profile = manager.sign_up(auth_type, BoxAny::new(params)).await?;
data_result_ok(user_profile.into())
let old_authenticator = manager.cloud_services.get_user_authenticator();
match manager.sign_up(authenticator, BoxAny::new(params)).await {
Ok(profile) => data_result_ok(UserProfilePB::from(profile)),
Err(err) => {
manager
.cloud_services
.set_user_authenticator(&old_authenticator);
return Err(err);
},
}
}
#[tracing::instrument(level = "debug", skip(manager))]
@@ -135,7 +151,6 @@ pub async fn set_appearance_setting(
if setting.theme.is_empty() {
setting.theme = APPEARANCE_DEFAULT_THEME.to_string();
}
store_preferences.set_object(APPEARANCE_SETTING_CACHE_KEY, setting)?;
Ok(())
}
+14 -18
View File
@@ -268,6 +268,11 @@ impl UserManager {
.map(|collab_db| Arc::downgrade(&collab_db))
}
#[cfg(debug_assertions)]
pub fn get_collab_backup_list(&self, uid: i64) -> Vec<String> {
self.database.get_collab_backup_list(uid)
}
/// Performs a user sign-in, initializing user awareness and sending relevant notifications.
///
/// This asynchronous function interacts with an external user service to authenticate and sign in a user
@@ -282,7 +287,8 @@ impl UserManager {
params: SignInParams,
authenticator: Authenticator,
) -> Result<UserProfile, FlowyError> {
self.update_authenticator(&authenticator).await;
self.cloud_services.set_user_authenticator(&authenticator);
let response: AuthResponse = self
.cloud_services
.get_user_service()?
@@ -321,10 +327,6 @@ impl UserManager {
Ok(user_profile)
}
pub(crate) async fn update_authenticator(&self, authenticator: &Authenticator) {
self.cloud_services.set_authenticator(authenticator.clone());
}
/// Manages the user sign-up process, potentially migrating data if necessary.
///
/// This asynchronous function interacts with an external authentication service to register and sign up a user
@@ -341,7 +343,7 @@ impl UserManager {
// sign out the current user if there is one
let migration_user = self.get_migration_user(&authenticator).await;
self.update_authenticator(&authenticator).await;
self.cloud_services.set_user_authenticator(&authenticator);
let auth_service = self.cloud_services.get_user_service()?;
let response: AuthResponse = auth_service.sign_up(params).await?;
let new_user_profile = UserProfile::from((&response, &authenticator));
@@ -513,15 +515,9 @@ impl UserManager {
// users opt for cloud storage, the application should automatically create a backup of the user
// data. This backup should be in the form of a zip file and stored locally on the user's disk
// for safety and data integrity purposes
if self.user_config.is_custom_storage_path() {
self
.database
.backup_or_restore(session.user_id, &session.user_workspace.id);
} else {
self
.database
.restore_if_need(session.user_id, &session.user_workspace.id);
}
self
.database
.backup_or_restore(session.user_id, &session.user_workspace.id);
}
/// Fetches the user profile for the given user ID.
@@ -723,7 +719,7 @@ impl UserManager {
authenticator: &Authenticator,
email: &str,
) -> Result<String, FlowyError> {
self.update_authenticator(authenticator).await;
self.cloud_services.set_user_authenticator(authenticator);
let auth_service = self.cloud_services.get_user_service()?;
let url = auth_service
@@ -738,8 +734,8 @@ impl UserManager {
oauth_provider: &str,
) -> Result<String, FlowyError> {
self
.update_authenticator(&Authenticator::AppFlowyCloud)
.await;
.cloud_services
.set_user_authenticator(&Authenticator::AppFlowyCloud);
let auth_service = self.cloud_services.get_user_service()?;
let url = auth_service
.generate_oauth_url_with_provider(oauth_provider)
@@ -59,9 +59,10 @@ impl UserDataMigration for FavoriteV1AndWorkspaceArrayMigration {
&encode.state_vector,
)
.map_err(internal_error)?;
write_txn.commit_transaction().map_err(internal_error)?;
}
write_txn.commit_transaction().map_err(internal_error)?;
Ok(())
}
}
@@ -48,9 +48,10 @@ impl UserDataMigration for WorkspaceTrashMapToSectionMigration {
&encode.state_vector,
)
.map_err(internal_error)?;
write_txn.commit_transaction().map_err(internal_error)?;
}
write_txn.commit_transaction().map_err(internal_error)?;
Ok(())
}
}
@@ -28,7 +28,7 @@ use parking_lot::{Mutex, RwLock};
use std::collections::{HashMap, HashSet};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use tracing::info;
use tracing::{debug, event, info, instrument};
pub(crate) struct ImportContext {
pub imported_session: Session,
@@ -92,15 +92,16 @@ pub(crate) fn import_appflowy_data_folder(
let views = collab_db.with_write_txn(|collab_write_txn| {
// use the old_to_new_id_map to keep track of the other collab object id and the new collab object id
let old_to_new_id_map = Arc::new(Mutex::new(OldToNewIdMap::new()));
let mut all_object_ids = imported_collab_read_txn
let mut all_imported_object_ids = imported_collab_read_txn
.get_all_docs()
.map(|iter| iter.collect::<Vec<String>>())
.unwrap_or_default();
// when doing import, we don't want to import the user workspace, database view tracker and the user awareness
all_object_ids.retain(|id| id != &imported_session.user_workspace.id);
all_object_ids.retain(|id| id != &imported_session.user_workspace.database_view_tracker_id);
all_object_ids
all_imported_object_ids.retain(|id| id != &imported_session.user_workspace.id);
all_imported_object_ids
.retain(|id| id != &imported_session.user_workspace.database_view_tracker_id);
all_imported_object_ids
.retain(|id| id != &awareness_oid_from_user_uuid(&imported_session.user_uuid).to_string());
// import database view tracker
@@ -118,32 +119,36 @@ pub(crate) fn import_appflowy_data_folder(
.flatten()
.cloned()
.collect();
all_object_ids.retain(|id| !database_view_ids.contains(id));
all_imported_object_ids.retain(|id| !database_view_ids.contains(id));
// load other collab objects
let collab_by_oid = load_collab_by_oid(
let imported_collab_by_oid = load_collab_by_oid(
imported_session.user_id,
&imported_collab_read_txn,
&all_object_ids,
&all_imported_object_ids,
);
// import the database
migrate_databases(
&old_to_new_id_map,
session,
collab_write_txn,
&mut all_object_ids,
&collab_by_oid,
&mut all_imported_object_ids,
&imported_collab_by_oid,
&row_object_ids,
&document_object_ids,
)?;
// the object ids now only contains the document collab object ids
for object_id in &all_object_ids {
if let Some(collab) = collab_by_oid.get(object_id) {
for object_id in &all_imported_object_ids {
if let Some(imported_collab) = imported_collab_by_oid.get(object_id) {
let new_object_id = old_to_new_id_map.lock().renew_id(object_id);
document_object_ids.lock().insert(new_object_id.clone());
tracing::debug!("migrate from: {}, to: {}", object_id, new_object_id,);
import_collab_object(collab, session.user_id, &new_object_id, collab_write_txn);
debug!("import from: {}, to: {}", object_id, new_object_id,);
import_collab_object(
imported_collab,
session.user_id,
&new_object_id,
collab_write_txn,
);
}
}
@@ -178,6 +183,9 @@ pub(crate) fn import_appflowy_data_folder(
collab_write_txn,
)?;
document_object_ids
.lock()
.insert(import_container_view_id.clone());
let import_container_view =
ViewBuilder::new(session.user_id, session.user_workspace.id.clone())
.with_view_id(import_container_view_id)
@@ -185,6 +193,7 @@ pub(crate) fn import_appflowy_data_folder(
.with_name(name)
.with_child_views(child_views)
.build();
Ok(vec![import_container_view])
},
}
@@ -247,10 +256,9 @@ fn migrate_databases<'a, W>(
old_to_new_id_map: &Arc<Mutex<OldToNewIdMap>>,
session: &Session,
collab_write_txn: &'a W,
object_ids: &mut Vec<String>,
collab_by_oid: &HashMap<String, Collab>,
imported_object_ids: &mut Vec<String>,
imported_collab_by_oid: &HashMap<String, Collab>,
row_object_ids: &Mutex<HashSet<String>>,
document_object_ids: &Mutex<HashSet<String>>,
) -> Result<(), PersistenceError>
where
W: YrsDocAction<'a>,
@@ -258,20 +266,20 @@ where
{
// Migrate databases
let mut database_object_ids = vec![];
let database_row_object_ids = RwLock::new(HashSet::new());
let imported_database_row_object_ids = RwLock::new(HashSet::new());
for object_id in &mut *object_ids {
if let Some(collab) = collab_by_oid.get(object_id) {
if !is_database_collab(collab) {
for object_id in &mut *imported_object_ids {
if let Some(database_collab) = imported_collab_by_oid.get(object_id) {
if !is_database_collab(database_collab) {
continue;
}
database_object_ids.push(object_id.clone());
reset_inline_view_id(collab, |old_inline_view_id| {
reset_inline_view_id(database_collab, |old_inline_view_id| {
old_to_new_id_map.lock().renew_id(&old_inline_view_id)
});
mut_database_views_with_collab(collab, |database_view| {
mut_database_views_with_collab(database_collab, |database_view| {
let new_view_id = old_to_new_id_map.lock().renew_id(&database_view.id);
let new_database_id = old_to_new_id_map
.lock()
@@ -284,64 +292,72 @@ where
let old_row_document_id = database_row_document_id_from_row_id(&old_row_id);
let new_row_id = old_to_new_id_map.lock().renew_id(&old_row_id);
let new_row_document_id = database_row_document_id_from_row_id(&new_row_id);
tracing::debug!("migrate row id: {} to {}", row_order.id, new_row_id);
tracing::debug!(
"migrate row document id: {} to {}",
old_row_document_id,
new_row_document_id
);
old_to_new_id_map
.lock()
.insert(old_row_document_id, new_row_document_id);
.insert(old_row_document_id.clone(), new_row_document_id);
row_order.id = RowId::from(new_row_id);
database_row_object_ids.write().insert(old_row_id);
imported_database_row_object_ids.write().insert(old_row_id);
});
// collect the ids
let row_ids = database_view
let new_row_ids = database_view
.row_orders
.iter()
.map(|order| order.id.clone().into_inner())
.collect::<Vec<String>>();
let row_document_ids = row_ids
.iter()
.map(|id| database_row_document_id_from_row_id(id))
.collect::<Vec<String>>();
row_object_ids.lock().extend(row_ids);
document_object_ids.lock().extend(row_document_ids);
row_object_ids.lock().extend(new_row_ids);
});
let new_object_id = old_to_new_id_map.lock().renew_id(object_id);
tracing::debug!(
debug!(
"migrate database from: {}, to: {}",
object_id,
new_object_id,
object_id, new_object_id,
);
import_collab_object(
database_collab,
session.user_id,
&new_object_id,
collab_write_txn,
);
import_collab_object(collab, session.user_id, &new_object_id, collab_write_txn);
}
}
let database_row_object_ids = database_row_object_ids.read();
let imported_database_row_object_ids = imported_database_row_object_ids.read();
// remove the database object ids from the object ids
object_ids.retain(|id| !database_object_ids.contains(id));
object_ids.retain(|id| !database_row_object_ids.contains(id));
imported_object_ids.retain(|id| !database_object_ids.contains(id));
imported_object_ids.retain(|id| !imported_database_row_object_ids.contains(id));
for object_id in &*database_row_object_ids {
if let Some(collab) = collab_by_oid.get(object_id) {
let new_object_id = old_to_new_id_map.lock().renew_id(object_id);
tracing::info!(
"migrate database row from: {}, to: {}",
object_id,
new_object_id,
for imported_row_id in &*imported_database_row_object_ids {
if let Some(imported_collab) = imported_collab_by_oid.get(imported_row_id) {
let new_row_id = old_to_new_id_map.lock().renew_id(imported_row_id);
info!(
"import database row from: {}, to: {}",
imported_row_id, new_row_id,
);
mut_row_with_collab(collab, |row_update| {
row_update.set_row_id(RowId::from(new_object_id.clone()));
mut_row_with_collab(imported_collab, |row_update| {
row_update.set_row_id(RowId::from(new_row_id.clone()));
});
import_collab_object(collab, session.user_id, &new_object_id, collab_write_txn);
import_collab_object(
imported_collab,
session.user_id,
&new_row_id,
collab_write_txn,
);
}
let imported_row_document_id = database_row_document_id_from_row_id(imported_row_id);
if imported_collab_by_oid
.get(&imported_row_document_id)
.is_some()
{
let new_row_document_id = old_to_new_id_map.lock().renew_id(&imported_row_document_id);
info!(
"map row document from: {}, to: {}",
imported_row_document_id, new_row_document_id,
);
}
}
Ok(())
@@ -354,7 +370,7 @@ where
{
let txn = collab.transact();
if let Err(err) = w_txn.create_new_doc(new_uid, &new_object_id, &txn) {
tracing::error!("import collab failed: {:?}", err);
tracing::error!("import collab:{} failed: {:?}", new_object_id, err);
}
}
@@ -519,6 +535,7 @@ impl DerefMut for OldToNewIdMap {
}
}
#[instrument(level = "debug", skip_all)]
pub async fn upload_imported_data(
uid: i64,
user_collab_db: Arc<RocksCollabDB>,
@@ -549,16 +566,20 @@ pub async fn upload_imported_data(
let object_by_collab_type = tokio::task::spawn_blocking(move || {
let collab_read = user_collab_db.read_txn();
let mut object_by_collab_type = HashMap::new();
event!(tracing::Level::DEBUG, "upload database collab data");
object_by_collab_type.insert(
CollabType::Database,
load_and_process_collab_data(uid, &collab_read, &database_object_ids),
);
event!(tracing::Level::DEBUG, "upload document collab data");
object_by_collab_type.insert(
CollabType::Document,
load_and_process_collab_data(uid, &collab_read, &document_object_ids),
);
event!(tracing::Level::DEBUG, "upload database row collab data");
object_by_collab_type.insert(
CollabType::DatabaseRow,
load_and_process_collab_data(uid, &collab_read, &row_object_ids),
@@ -573,17 +594,26 @@ pub async fn upload_imported_data(
let mut size_counter = 0;
let mut objects: Vec<UserCollabParams> = vec![];
let upload_size_limit = 2 * 1024 * 1024;
for (collab_type, encoded_v1_by_oid) in object_by_collab_type {
for (collab_type, encoded_collab_by_oid) in object_by_collab_type {
info!(
"Batch import collab:{} ids: {:?}",
collab_type,
encoded_v1_by_oid.keys(),
encoded_collab_by_oid.keys(),
);
for (oid, encoded_v1) in encoded_v1_by_oid {
let obj_size = encoded_v1.len();
for (oid, encoded_collab) in encoded_collab_by_oid {
let obj_size = encoded_collab.len();
if size_counter + obj_size > upload_size_limit && !objects.is_empty() {
// When the limit is exceeded, batch create with the current list of objects
// and reset for the next batch.
info!(
"Exceeded maximum payload size. Batch creating collab objects: {}, payload size: {}",
objects
.iter()
.map(|o| o.object_id.clone())
.collect::<Vec<_>>()
.join(", "),
size_counter
);
user_cloud_service
.batch_create_collab_object(workspace_id, objects)
.await?;
@@ -594,7 +624,7 @@ pub async fn upload_imported_data(
// Add the current object to the batch.
objects.push(UserCollabParams {
object_id: oid,
encoded_collab_v1: encoded_v1,
encoded_collab,
collab_type: collab_type.clone(),
});
size_counter += obj_size;
@@ -619,6 +649,7 @@ pub async fn upload_imported_data(
Ok(())
}
#[instrument(level = "debug", skip_all)]
fn load_and_process_collab_data<'a, R>(
uid: i64,
collab_read: &R,
@@ -635,7 +666,7 @@ where
.encode_collab_v1()
.encode_to_bytes()
.ok()
.map(|encoded_v1| (oid, encoded_v1))
.map(|encoded_collab| (oid, encoded_collab))
})
.collect()
}
@@ -7,6 +7,7 @@ use crate::services::data_import::ImportContext;
use collab::preclude::Collab;
use flowy_folder_deps::entities::ImportData;
use std::sync::Arc;
use tracing::instrument;
pub enum ImportDataSource {
AppFlowyDataFolder {
@@ -26,6 +27,7 @@ pub(crate) fn import_data(
import_appflowy_data_folder(session, &session.user_workspace.id, &collab_db, context)
}
#[instrument(level = "debug", skip_all)]
pub fn load_collab_by_oid<'a, R>(
uid: i64,
collab_read_txn: &R,
@@ -44,7 +46,7 @@ where
Ok(_) => {
collab_by_oid.insert(object_id.clone(), collab);
},
Err(err) => tracing::error!("🔴Initialize migration collab failed: {:?} ", err),
Err(err) => tracing::error!("🔴import collab:{} failed: {:?} ", object_id, err),
}
}
@@ -84,6 +84,17 @@ impl UserDB {
}
}
#[cfg(debug_assertions)]
pub fn get_collab_backup_list(&self, uid: i64) -> Vec<String> {
let collab_db_path = self.paths.collab_db_path(uid);
if let Ok(history_folder) = self.paths.collab_db_history(uid, true) {
return CollabDBZipBackup::new(collab_db_path.clone(), history_folder)
.get_backup_list()
.unwrap_or_default();
}
vec![]
}
#[instrument(level = "debug", skip_all)]
pub fn restore_if_need(&self, uid: i64, workspace_id: &str) {
if let Ok(history_folder) = self.paths.collab_db_history(uid, false) {
@@ -224,9 +235,16 @@ impl CollabDBZipBackup {
#[instrument(name = "backup_collab_db", skip_all, err)]
pub fn backup(&self) -> io::Result<()> {
let today_zip_file = self
.history_folder
.join(format!("collab_db_{}.zip", today_zip_timestamp()));
let file_name = match std::env::var("APP_VERSION") {
Ok(version_num) => {
format!("collab_db_{}_{}.zip", version_num, today_zip_timestamp())
},
Err(_) => {
format!("collab_db_{}.zip", today_zip_timestamp())
},
};
let today_zip_file = self.history_folder.join(file_name);
// Remove today's existing zip file if it exists
if !today_zip_file.exists() {
@@ -240,11 +258,29 @@ impl CollabDBZipBackup {
}
// Clean up old backups
self.clean_old_backups()?;
if let Err(err) = self.clean_old_backups() {
error!("Clean up old backups failed: {:?}", err);
}
Ok(())
}
#[cfg(debug_assertions)]
pub fn get_backup_list(&self) -> io::Result<Vec<String>> {
let mut backups = Vec::new();
for entry in fs::read_dir(&self.history_folder)? {
let entry = entry?;
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("zip") {
if let Some(file_name) = path.file_stem().and_then(|s| s.to_str()) {
backups.push(file_name.to_string());
}
}
}
backups.sort();
Ok(backups)
}
#[instrument(skip_all, err)]
pub fn restore_latest_backup(&self) -> io::Result<()> {
let mut latest_zip: Option<(String, PathBuf)> = None;
@@ -258,7 +294,7 @@ impl CollabDBZipBackup {
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("zip") {
if let Some(file_name) = path.file_stem().and_then(|s| s.to_str()) {
if let Some(timestamp_str) = file_name.strip_prefix("collab_db_") {
if let Some(timestamp_str) = file_name.split('_').last() {
match latest_zip {
Some((latest_timestamp, _)) if timestamp_str > latest_timestamp.as_str() => {
latest_zip = Some((timestamp_str.to_string(), path));
@@ -309,6 +345,7 @@ impl CollabDBZipBackup {
// Remove backups older than 10 days
let threshold_str = threshold_date.format(zip_time_format()).to_string();
info!("Current backup: {:?}", backups.len());
// If there are more than 10 backups, remove the oldest ones
while backups.len() > 10 {
if let Some((date_str, path)) = backups.first() {
+1 -1
View File
@@ -9,7 +9,7 @@ edition = "2018"
tracing-subscriber = { version = "0.3.17", features = ["registry", "env-filter", "ansi", "json"] }
tracing-bunyan-formatter = "0.3.9"
tracing-appender = "0.2.2"
tracing-appender = "0.2.3"
tracing-core = "0.1"
tracing.workspace = true
serde_json.workspace = true
+9 -1
View File
@@ -3,6 +3,7 @@ use std::sync::RwLock;
use chrono::Local;
use lazy_static::lazy_static;
use tracing::subscriber::set_global_default;
use tracing_appender::rolling::Rotation;
use tracing_appender::{non_blocking::WorkerGuard, rolling::RollingFileAppender};
use tracing_bunyan_formatter::JsonStorageLayer;
use tracing_subscriber::fmt::format::Writer;
@@ -25,10 +26,17 @@ pub struct Builder {
impl Builder {
pub fn new(name: &str, directory: &str) -> Self {
let file_appender = RollingFileAppender::builder()
.rotation(Rotation::DAILY)
.filename_prefix(name)
.max_log_files(6)
.build(directory)
.unwrap_or(tracing_appender::rolling::daily(directory, name));
Builder {
name: name.to_owned(),
env_filter: "Info".to_owned(),
file_appender: tracing_appender::rolling::daily(directory, name),
file_appender,
}
}
+15
View File
@@ -47,6 +47,7 @@ run_task = { name = [
#
[tasks.sdk-dev-build]
dependencies = ["set-app-version"]
private = true
script = [
"""
@@ -58,6 +59,7 @@ script = [
script_runner = "@shell"
[tasks.sdk-dev-build.mac]
dependencies = ["set-app-version"]
private = true
script = [
"""
@@ -69,6 +71,7 @@ script = [
script_runner = "@shell"
[tasks.sdk-dev-build.windows]
dependencies = ["set-app-version"]
private = true
script = [
"""
@@ -93,6 +96,7 @@ run_task = { name = [
#
[tasks.sdk-release-build]
dependencies = ["set-app-version"]
script = [
"""
cd rust-lib/
@@ -103,6 +107,7 @@ script = [
script_runner = "@shell"
[tasks.sdk-release-build.mac]
dependencies = ["set-app-version"]
script = [
"""
cd rust-lib/
@@ -172,3 +177,13 @@ script = [
""",
]
script_runner = "@duckscript"
[tasks.set-app-version]
script = ["""
if is_empty ${APP_VERSION}
APP_VERSION = set ${APPFLOWY_VERSION}
set_env APP_VERSION ${APPFLOWY_VERSION}
end
echo APP_VERSION: ${APP_VERSION}
"""]
script_runner = "@duckscript"
-17
View File
@@ -7,7 +7,6 @@ linux_alias = "appflowy-linux"
dependencies = ["appflowy-core-release"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build",
"copy-to-product",
] }
@@ -16,7 +15,6 @@ script_runner = "@shell"
[tasks.appflowy-macos-universal]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build",
"copy-to-product",
] }
@@ -71,7 +69,6 @@ linux_alias = "appflowy-linux-dev"
dependencies = ["appflowy-core-dev-ios"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build-ios",
] }
script_runner = "@shell"
@@ -80,7 +77,6 @@ script_runner = "@shell"
dependencies = ["appflowy-core-dev-android"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build-android",
] }
script_runner = "@shell"
@@ -89,7 +85,6 @@ script_runner = "@shell"
dependencies = ["appflowy-core-dev-android"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build-android",
] }
script_runner = "@shell"
@@ -98,7 +93,6 @@ script_runner = "@shell"
dependencies = ["appflowy-core-dev"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build",
"copy-to-product",
] }
@@ -108,7 +102,6 @@ script_runner = "@shell"
dependencies = ["appflowy-core-dev"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build",
"copy-to-product",
] }
@@ -117,7 +110,6 @@ run_task = { name = [
dependencies = ["appflowy-core-dev"]
run_task = { name = [
"code_generation",
"set-app-version",
"flutter-build",
"copy-to-product",
] }
@@ -216,15 +208,6 @@ script = [
]
script_runner = "@duckscript"
[tasks.set-app-version]
script = ["""
if is_empty ${APP_VERSION}
APP_VERSION = set ${CURRENT_APP_VERSION}
set_env APP_VERSION ${CURRENT_APP_VERSION}
end
echo APP_VERSION: ${APP_VERSION}
"""]
script_runner = "@duckscript"
# The following tasks will create an archive that will be used on the GitHub Releases section
# The archives are created using different compression programs depending on the target OS
+4 -2
View File
@@ -12,7 +12,7 @@ condition = { env_set = [
[tasks.appflowy-core-dev-ios]
category = "Build"
dependencies = ["env_check"]
dependencies = ["env_check", "set-app-version"]
run_task = { name = [
"setup-crate-type",
"sdk-build-ios",
@@ -21,6 +21,7 @@ run_task = { name = [
] }
[tasks.sdk-build-ios]
dependencies = ["set-app-version"]
private = true
script = [
"""
@@ -40,7 +41,7 @@ script_runner = "@shell"
[tasks.appflowy-core-dev-android]
category = "Build"
dependencies = ["env_check"]
dependencies = ["env_check", "set-app-version"]
run_task = { name = [
"setup-crate-type",
"sdk-build-android",
@@ -49,6 +50,7 @@ run_task = { name = [
] }
[tasks.sdk-build-android]
dependencies = ["set-app-version"]
private = true
script = [
"""