mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
tests: more cloud test (#4204)
* test: add anon user test * chore: add to runner * test: fix * test: fix * test: add tests * chore: add test * chore: fix warn * chore: fix warn * fix: build * fix: test * chore: rename * chore: fix test * chore: fix test * chore: fix test * chore: disable test
This commit is contained in:
parent
9b55f5bc7f
commit
a49b009980
25
.github/workflows/rust_ci.yaml
vendored
25
.github/workflows/rust_ci.yaml
vendored
@ -68,6 +68,31 @@ jobs:
|
||||
echo SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }} >> .env.ci
|
||||
echo SUPABASE_JWT_SECRET=${{ secrets.SUPABASE_JWT_SECRET }} >> .env.ci
|
||||
|
||||
- name: Checkout appflowy cloud code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: AppFlowy-IO/AppFlowy-Cloud
|
||||
path: AppFlowy-Cloud
|
||||
depth: 1
|
||||
|
||||
- name: Prepare appflowy cloud env
|
||||
working-directory: AppFlowy-Cloud
|
||||
run: |
|
||||
# log level
|
||||
cp dev.env .env
|
||||
sed -i 's|RUST_LOG=.*|RUST_LOG=trace|' .env
|
||||
sed -i 's/GOTRUE_SMTP_USER=.*/GOTRUE_SMTP_USER=${{ secrets.INTEGRATION_TEST_GOTRUE_SMTP_USER }}/' .env
|
||||
sed -i 's/GOTRUE_SMTP_PASS=.*/GOTRUE_SMTP_PASS=${{ secrets.INTEGRATION_TEST_GOTRUE_SMTP_PASS }}/' .env
|
||||
sed -i 's/GOTRUE_SMTP_ADMIN_EMAIL=.*/GOTRUE_SMTP_ADMIN_EMAIL=${{ secrets.INTEGRATION_TEST_GOTRUE_SMTP_ADMIN_EMAIL }}/' .env
|
||||
sed -i 's/GOTRUE_EXTERNAL_GOOGLE_ENABLED=.*/GOTRUE_EXTERNAL_GOOGLE_ENABLED=true/' .env
|
||||
sed -i 's|API_EXTERNAL_URL=.*|API_EXTERNAL_URL=http://localhost|' .env
|
||||
cat .env
|
||||
|
||||
- name: Run Docker-Compose
|
||||
working-directory: AppFlowy-Cloud
|
||||
run: |
|
||||
docker compose up -d
|
||||
|
||||
- name: Run rust-lib tests
|
||||
working-directory: frontend/rust-lib
|
||||
run: RUST_LOG=info RUST_BACKTRACE=1 cargo test --no-default-features --features="rev-sqlite"
|
||||
|
Binary file not shown.
@ -16,7 +16,7 @@ void main() {
|
||||
await tester.initializeAppFlowy();
|
||||
|
||||
await tester.tapGoButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
await tester.openSettings();
|
||||
|
||||
await tester.openSettingsPage(SettingsPage.appearance);
|
||||
@ -48,7 +48,7 @@ void main() {
|
||||
await tester.initializeAppFlowy();
|
||||
|
||||
await tester.tapGoButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
await tester.openSettings();
|
||||
|
||||
await tester.openSettingsPage(SettingsPage.appearance);
|
||||
|
@ -0,0 +1,68 @@
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/env/cloud_env.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/auth/af_cloud_mock_auth_service.dart';
|
||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../util/dir.dart';
|
||||
import '../util/mock/mock_file_picker.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('appflowy cloud', () {
|
||||
testWidgets('anon user and then sign in', (tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloud,
|
||||
);
|
||||
|
||||
tester.expectToSeeText(LocaleKeys.signIn_loginStartWithAnonymous.tr());
|
||||
await tester.tapGoButton();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// reanme the name of the anon user
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
final userNameFinder = find.descendant(
|
||||
of: find.byType(SettingsUserView),
|
||||
matching: find.byType(UserNameInput),
|
||||
);
|
||||
await tester.enterText(userNameFinder, 'local_user');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// sign up with Google
|
||||
await tester.tapGoogleLoginInButton();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// sign out
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
await tester.logout();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// tap the continue as anonymous button
|
||||
await tester
|
||||
.tapButton(find.text(LocaleKeys.signIn_continueAnonymousUser.tr()));
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// assert the name of the anon user is local_user
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
final userNameInput = tester.widget(userNameFinder) as UserNameInput;
|
||||
expect(userNameInput.name, 'local_user');
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/env/cloud_env.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/auth/af_cloud_mock_auth_service.dart';
|
||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/sign_in_anonymous_button.dart';
|
||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../util/database_test_op.dart';
|
||||
import '../util/dir.dart';
|
||||
import '../util/mock/mock_file_picker.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('appflowy cloud', () {
|
||||
testWidgets('anon user -> af cloud -> continue anon', (tester) async {
|
||||
await tester.initializeAppFlowy(
|
||||
cloudType: AuthenticatorType.appflowyCloud,
|
||||
);
|
||||
|
||||
tester.expectToSeeText(LocaleKeys.signIn_loginStartWithAnonymous.tr());
|
||||
await tester.tapGoButton();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// reanme the name of the anon user
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
final userNameFinder = find.descendant(
|
||||
of: find.byType(SettingsUserView),
|
||||
matching: find.byType(UserNameInput),
|
||||
);
|
||||
await tester.enterText(userNameFinder, 'local_user');
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
await tester.tapEscButton();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// sign up with Google
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// sign out
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
await tester.logout();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
tester.expectToSeeText(LocaleKeys.signIn_continueAnonymousUser.tr());
|
||||
// tap the continue as anonymous button
|
||||
await tester.tapButton(find.byType(SignInAnonymousButton));
|
||||
|
||||
await tester.expectToSeeHomePage();
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
final userNameInput = tester.widget(userNameFinder) as UserNameInput;
|
||||
expect(userNameInput.name, 'local_user');
|
||||
});
|
||||
});
|
||||
}
|
@ -25,7 +25,7 @@ void main() {
|
||||
cloudType: AuthenticatorType.appflowyCloud,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
});
|
||||
|
||||
testWidgets('sign out', (tester) async {
|
||||
|
@ -1,14 +1,17 @@
|
||||
import 'empty_test.dart' as empty_test;
|
||||
import 'empty_test.dart' as preset_af_cloud_env_test;
|
||||
import 'appflowy_cloud_auth_test.dart' as appflowy_cloud_auth_test;
|
||||
import 'document_sync_test.dart' as document_sync_test;
|
||||
import 'user_setting_sync_test.dart' as user_sync_test;
|
||||
// import 'anon_user_continue_test.dart' as anon_user_continue_test;
|
||||
|
||||
Future<void> main() async {
|
||||
empty_test.main();
|
||||
preset_af_cloud_env_test.main();
|
||||
|
||||
appflowy_cloud_auth_test.main();
|
||||
|
||||
document_sync_test.main();
|
||||
|
||||
user_sync_test.main();
|
||||
|
||||
// anon_user_continue_test.main();
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ void main() {
|
||||
email: email,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// create a new document called Sample
|
||||
await tester.createNewPageWithName(
|
||||
@ -52,8 +52,7 @@ void main() {
|
||||
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
await tester.tapButton(find.byType(SettingLogoutButton));
|
||||
tester.expectToSeeText(LocaleKeys.button_ok.tr());
|
||||
await tester.logout();
|
||||
});
|
||||
|
||||
testWidgets('sync doc from server', (tester) async {
|
||||
@ -62,7 +61,7 @@ void main() {
|
||||
email: email,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||
|
||||
// The document will be synced from the server
|
||||
|
@ -15,7 +15,7 @@ void main() {
|
||||
testWidgets('sign in with supabase', (tester) async {
|
||||
await tester.initializeAppFlowy(cloudType: AuthenticatorType.supabase);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
});
|
||||
|
||||
testWidgets('sign out with supabase', (tester) async {
|
||||
|
@ -36,7 +36,7 @@ void main() {
|
||||
email: email,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.user);
|
||||
@ -74,7 +74,7 @@ void main() {
|
||||
email: email,
|
||||
);
|
||||
await tester.tapGoogleLoginInButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.openSettings();
|
||||
|
@ -19,7 +19,7 @@ void main() {
|
||||
await tester.initializeAppFlowy();
|
||||
|
||||
await tester.tapGoButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
await tester.openSettings();
|
||||
await tester.openSettingsPage(SettingsPage.appearance);
|
||||
@ -71,7 +71,7 @@ void main() {
|
||||
await tester.initializeAppFlowy();
|
||||
|
||||
await tester.tapGoButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
|
@ -14,7 +14,7 @@ void main() {
|
||||
await tester.initializeAppFlowy();
|
||||
|
||||
await tester.tapGoButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
await tester.openSettings();
|
||||
|
||||
await tester.openSettingsPage(SettingsPage.language);
|
||||
|
@ -33,7 +33,7 @@ void main() {
|
||||
);
|
||||
|
||||
await tester.tapGoButton();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// switch to user B
|
||||
{
|
||||
@ -51,7 +51,7 @@ void main() {
|
||||
);
|
||||
await tester.tapCustomLocationButton();
|
||||
await tester.pumpAndSettle();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// set user name for userB
|
||||
await tester.openSettings();
|
||||
@ -71,7 +71,7 @@ void main() {
|
||||
await tester.tapCustomLocationButton();
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
tester.expectToSeeUserName(userA);
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ void main() {
|
||||
await tester.tapCustomLocationButton();
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
tester.expectToSeeUserName(userB);
|
||||
}
|
||||
});
|
||||
@ -99,7 +99,7 @@ void main() {
|
||||
await tester.tapGoButton();
|
||||
|
||||
// home and readme document
|
||||
tester.expectToSeeHomePage();
|
||||
await tester.expectToSeeHomePage();
|
||||
|
||||
// open settings and restore the location
|
||||
await tester.openSettings();
|
||||
|
@ -1,16 +1,27 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_supabase_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'base.dart';
|
||||
import 'expectation.dart';
|
||||
|
||||
extension AppFlowyAuthTest on WidgetTester {
|
||||
Future<void> tapGoogleLoginInButton() async {
|
||||
await tapButton(find.byKey(const Key('signInWithGoogleButton')));
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await tapButton(find.byType(SettingLogoutButton));
|
||||
|
||||
expectToSeeText(LocaleKeys.button_ok.tr());
|
||||
await tapButtonWithName(LocaleKeys.button_ok.tr());
|
||||
}
|
||||
|
||||
Future<void> tapSignInAsGuest() async {
|
||||
await tapButton(find.byType(SignInAnonymousButton));
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
@ -33,21 +32,24 @@ extension AppFlowyTestBase on WidgetTester {
|
||||
Future<FlowyTestContext> initializeAppFlowy({
|
||||
// use to append after the application data directory
|
||||
String? pathExtension,
|
||||
// use to specify the application data directory, if not specified, a temporary directory will be used.
|
||||
String? dataDirectory,
|
||||
Size windowsSize = const Size(1600, 1200),
|
||||
AuthenticatorType? cloudType,
|
||||
String? email,
|
||||
}) async {
|
||||
// view.physicalSize = windowsSize;
|
||||
binding.setSurfaceSize(windowsSize);
|
||||
// addTearDown(() => binding.setSurfaceSize(null));
|
||||
|
||||
mockHotKeyManagerHandlers();
|
||||
final directory = await mockApplicationDataStorage(
|
||||
pathExtension: pathExtension,
|
||||
);
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final applicationDataDirectory = dataDirectory ??
|
||||
await mockApplicationDataStorage(
|
||||
pathExtension: pathExtension,
|
||||
);
|
||||
|
||||
await FlowyRunner.run(
|
||||
FlowyApp(),
|
||||
AppFlowyApplication(),
|
||||
IntegrationMode.integrationTest,
|
||||
rustEnvsBuilder: () {
|
||||
final rustEnvs = <String, String>{};
|
||||
@ -93,9 +95,10 @@ extension AppFlowyTestBase on WidgetTester {
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
await waitUntilSignInPageShow();
|
||||
return FlowyTestContext(
|
||||
applicationDataDirectory: directory,
|
||||
applicationDataDirectory: applicationDataDirectory,
|
||||
);
|
||||
}
|
||||
|
||||
@ -110,27 +113,6 @@ extension AppFlowyTestBase on WidgetTester {
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> mockApplicationDataStorage({
|
||||
// use to append after the application data directory
|
||||
String? pathExtension,
|
||||
}) async {
|
||||
final dir = await getTemporaryDirectory();
|
||||
|
||||
// Use a random uuid to avoid conflict.
|
||||
String path = p.join(dir.path, 'appflowy_integration_test', uuid());
|
||||
if (pathExtension != null && pathExtension.isNotEmpty) {
|
||||
path = '$path/$pathExtension';
|
||||
}
|
||||
final directory = Directory(path);
|
||||
if (!directory.existsSync()) {
|
||||
await directory.create(recursive: true);
|
||||
}
|
||||
|
||||
MockApplicationDataStorage.initialPath = directory.path;
|
||||
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
Future<void> waitUntilSignInPageShow() async {
|
||||
if (isAuthEnabled) {
|
||||
final finder = find.byType(SignInAnonymousButton);
|
||||
@ -143,16 +125,22 @@ extension AppFlowyTestBase on WidgetTester {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> waitForSeconds(int seconds) async {
|
||||
await Future.delayed((Duration(seconds: seconds)), () {});
|
||||
}
|
||||
|
||||
Future<void> pumpUntilFound(
|
||||
Finder finder, {
|
||||
Duration timeout = const Duration(seconds: 10),
|
||||
Duration pumpInterval =
|
||||
const Duration(milliseconds: 50), // Interval between pumps
|
||||
}) async {
|
||||
bool timerDone = false;
|
||||
final timer = Timer(timeout, () => timerDone = true);
|
||||
while (timerDone != true) {
|
||||
await pump();
|
||||
while (!timerDone) {
|
||||
await pump(pumpInterval); // Pump with an interval
|
||||
if (any(finder)) {
|
||||
timerDone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer.cancel();
|
||||
@ -273,3 +261,24 @@ Future<void> useAppFlowyCloud() async {
|
||||
await setAuthenticatorType(AuthenticatorType.appflowyCloud);
|
||||
await setAppFlowyCloudUrl(Some(TestEnv.afCloudUrl));
|
||||
}
|
||||
|
||||
Future<String> mockApplicationDataStorage({
|
||||
// use to append after the application data directory
|
||||
String? pathExtension,
|
||||
}) async {
|
||||
final dir = await getTemporaryDirectory();
|
||||
|
||||
// Use a random uuid to avoid conflict.
|
||||
String path = p.join(dir.path, 'appflowy_integration_test', uuid());
|
||||
if (pathExtension != null && pathExtension.isNotEmpty) {
|
||||
path = '$path/$pathExtension';
|
||||
}
|
||||
final directory = Directory(path);
|
||||
if (!directory.existsSync()) {
|
||||
await directory.create(recursive: true);
|
||||
}
|
||||
|
||||
MockApplicationDataStorage.initialPath = directory.path;
|
||||
|
||||
return directory.path;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:archive/archive.dart';
|
||||
|
||||
Future<void> deleteDirectoriesWithSameBaseNameAsPrefix(
|
||||
String path,
|
||||
@ -28,3 +29,25 @@ Future<void> deleteDirectoriesWithSameBaseNameAsPrefix(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> unzipFile(File zipFile, Directory targetDirectory) async {
|
||||
// Read the Zip file from disk.
|
||||
final bytes = zipFile.readAsBytesSync();
|
||||
|
||||
// Decode the Zip file
|
||||
final archive = ZipDecoder().decodeBytes(bytes);
|
||||
|
||||
// Extract the contents of the Zip archive to disk.
|
||||
for (final file in archive) {
|
||||
final filename = file.name;
|
||||
if (file.isFile) {
|
||||
final data = file.content as List<int>;
|
||||
File(p.join(targetDirectory.path, filename))
|
||||
..createSync(recursive: true)
|
||||
..writeAsBytesSync(data);
|
||||
} else {
|
||||
Directory(p.join(targetDirectory.path, filename))
|
||||
.createSync(recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,20 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'util.dart';
|
||||
|
||||
// const String readme = 'Read me';
|
||||
const String gettingStarted = 'Getting started';
|
||||
|
||||
extension Expectation on WidgetTester {
|
||||
/// Expect to see the home page and with a default read me page.
|
||||
void expectToSeeHomePage() {
|
||||
expect(find.byType(HomeStack), findsOneWidget);
|
||||
expect(find.textContaining(gettingStarted), findsWidgets);
|
||||
Future<void> expectToSeeHomePage() async {
|
||||
final finder = find.byType(HomeStack);
|
||||
await pumpUntilFound(finder);
|
||||
expect(finder, findsOneWidget);
|
||||
|
||||
final docFinder = find.textContaining(gettingStarted);
|
||||
await pumpUntilFound(docFinder);
|
||||
}
|
||||
|
||||
/// Expect to see the page name on the home page.
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_user.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
|
||||
@ -13,7 +14,7 @@ import 'base.dart';
|
||||
extension AppFlowySettings on WidgetTester {
|
||||
/// Open settings page
|
||||
Future<void> openSettings() async {
|
||||
final settingsButton = find.byTooltip(LocaleKeys.settings_menu_open.tr());
|
||||
final settingsButton = find.byType(UserSettingButton);
|
||||
expect(settingsButton, findsOneWidget);
|
||||
await tapButton(settingsButton);
|
||||
final settingsDialog = find.byType(SettingsDialog);
|
||||
|
@ -131,7 +131,7 @@ void _resolveUserDeps(GetIt getIt, IntegrationMode mode) {
|
||||
case AuthenticatorType.local:
|
||||
getIt.registerFactory<AuthService>(
|
||||
() => BackendAuthService(
|
||||
AuthTypePB.Local,
|
||||
AuthenticatorPB.Local,
|
||||
),
|
||||
);
|
||||
break;
|
||||
|
@ -3,7 +3,7 @@ import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/presentation/screens/splash_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FlowyApp implements EntryPoint {
|
||||
class AppFlowyApplication implements EntryPoint {
|
||||
@override
|
||||
Widget create(LaunchConfiguration config) {
|
||||
return SplashScreen(
|
||||
|
@ -29,14 +29,30 @@ class FlowyRunnerContext {
|
||||
FlowyRunnerContext({required this.applicationDataDirectory});
|
||||
}
|
||||
|
||||
Future<void> runAppFlowy() async {
|
||||
await FlowyRunner.run(
|
||||
FlowyApp(),
|
||||
integrationMode(),
|
||||
);
|
||||
Future<void> runAppFlowy({bool isAnon = false}) async {
|
||||
if (kReleaseMode) {
|
||||
await FlowyRunner.run(
|
||||
AppFlowyApplication(),
|
||||
integrationMode(),
|
||||
isAnon: isAnon,
|
||||
);
|
||||
} else {
|
||||
// When running the app in integration test mode, we need to
|
||||
// specify the mode to run the app again.
|
||||
await FlowyRunner.run(
|
||||
AppFlowyApplication(),
|
||||
FlowyRunner.currentMode,
|
||||
didInitGetItCallback: IntegrationTestHelper.didInitGetItCallback,
|
||||
rustEnvsBuilder: IntegrationTestHelper.rustEnvsBuilder,
|
||||
isAnon: isAnon,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FlowyRunner {
|
||||
// This variable specifies the initial mode of the app when it is launched for the first time.
|
||||
// The same mode will be automatically applied in subsequent executions when the runAppFlowy()
|
||||
// method is called.
|
||||
static var currentMode = integrationMode();
|
||||
|
||||
static Future<FlowyRunnerContext> run(
|
||||
@ -55,6 +71,13 @@ class FlowyRunner {
|
||||
bool isAnon = false,
|
||||
}) async {
|
||||
currentMode = mode;
|
||||
|
||||
// Only set the mode when it's not release mode
|
||||
if (!kReleaseMode) {
|
||||
IntegrationTestHelper.didInitGetItCallback = didInitGetItCallback;
|
||||
IntegrationTestHelper.rustEnvsBuilder = rustEnvsBuilder;
|
||||
}
|
||||
|
||||
// Clear all the states in case of rebuilding.
|
||||
await getIt.reset();
|
||||
|
||||
@ -220,3 +243,9 @@ IntegrationMode integrationMode() {
|
||||
|
||||
return IntegrationMode.develop;
|
||||
}
|
||||
|
||||
/// Only used for integration test
|
||||
class IntegrationTestHelper {
|
||||
static Future Function()? didInitGetItCallback;
|
||||
static Map<String, String> Function()? rustEnvsBuilder;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ class AppFlowyCloudDeepLink {
|
||||
(_) async {
|
||||
final deviceId = await getDeviceId();
|
||||
final payload = OauthSignInPB(
|
||||
authType: AuthTypePB.AFCloud,
|
||||
authType: AuthenticatorPB.AppFlowyCloud,
|
||||
map: {
|
||||
AuthServiceMapKeys.signInURL: uri.toString(),
|
||||
AuthServiceMapKeys.deviceId: deviceId,
|
||||
|
@ -17,7 +17,7 @@ class AppFlowyCloudAuthService implements AuthService {
|
||||
AppFlowyCloudAuthService();
|
||||
|
||||
final BackendAuthService _backendAuthService = BackendAuthService(
|
||||
AuthTypePB.AFCloud,
|
||||
AuthenticatorPB.AppFlowyCloud,
|
||||
);
|
||||
|
||||
@override
|
||||
|
@ -18,7 +18,7 @@ class AppFlowyCloudMockAuthService implements AuthService {
|
||||
: userEmail = email ?? "${uuid()}@appflowy.io";
|
||||
|
||||
final BackendAuthService _appFlowyAuthService =
|
||||
BackendAuthService(AuthTypePB.Supabase);
|
||||
BackendAuthService(AuthenticatorPB.Supabase);
|
||||
|
||||
@override
|
||||
Future<Either<FlowyError, UserProfilePB>> signUp({
|
||||
@ -45,7 +45,7 @@ class AppFlowyCloudMockAuthService implements AuthService {
|
||||
Map<String, String> params = const {},
|
||||
}) async {
|
||||
final payload = SignInUrlPayloadPB.create()
|
||||
..authType = AuthTypePB.AFCloud
|
||||
..authType = AuthenticatorPB.AppFlowyCloud
|
||||
// don't use nanoid here, the gotrue server will transform the email
|
||||
..email = userEmail;
|
||||
|
||||
@ -55,7 +55,7 @@ class AppFlowyCloudMockAuthService implements AuthService {
|
||||
return getSignInURLResult.fold(
|
||||
(urlPB) async {
|
||||
final payload = OauthSignInPB(
|
||||
authType: AuthTypePB.AFCloud,
|
||||
authType: AuthenticatorPB.AppFlowyCloud,
|
||||
map: {
|
||||
AuthServiceMapKeys.signInURL: urlPB.signInUrl,
|
||||
AuthServiceMapKeys.deviceId: deviceId,
|
||||
|
@ -14,7 +14,7 @@ import '../../../generated/locale_keys.g.dart';
|
||||
import 'device_id.dart';
|
||||
|
||||
class BackendAuthService implements AuthService {
|
||||
final AuthTypePB authType;
|
||||
final AuthenticatorPB authType;
|
||||
|
||||
BackendAuthService(this.authType);
|
||||
|
||||
@ -73,7 +73,7 @@ class BackendAuthService implements AuthService {
|
||||
..email = userEmail
|
||||
..password = password
|
||||
// When sign up as guest, the auth type is always local.
|
||||
..authType = AuthTypePB.Local
|
||||
..authType = AuthenticatorPB.Local
|
||||
..deviceId = await getDeviceId();
|
||||
final response = await UserEventSignUp(request).send().then(
|
||||
(value) => value.swap(),
|
||||
@ -84,7 +84,7 @@ class BackendAuthService implements AuthService {
|
||||
@override
|
||||
Future<Either<FlowyError, UserProfilePB>> signUpWithOAuth({
|
||||
required String platform,
|
||||
AuthTypePB authType = AuthTypePB.Local,
|
||||
AuthenticatorPB authType = AuthenticatorPB.Local,
|
||||
Map<String, String> params = const {},
|
||||
}) async {
|
||||
return left(
|
||||
|
@ -22,7 +22,7 @@ class SupabaseAuthService implements AuthService {
|
||||
GoTrueClient get _auth => _client.auth;
|
||||
|
||||
final BackendAuthService _backendAuthService = BackendAuthService(
|
||||
AuthTypePB.Supabase,
|
||||
AuthenticatorPB.Supabase,
|
||||
);
|
||||
|
||||
@override
|
||||
@ -171,7 +171,7 @@ class SupabaseAuthService implements AuthService {
|
||||
required Map<String, String> map,
|
||||
}) async {
|
||||
final payload = OauthSignInPB(
|
||||
authType: AuthTypePB.Supabase,
|
||||
authType: AuthenticatorPB.Supabase,
|
||||
map: map,
|
||||
);
|
||||
|
||||
|
@ -21,7 +21,7 @@ class SupabaseMockAuthService implements AuthService {
|
||||
GoTrueClient get _auth => _client.auth;
|
||||
|
||||
final BackendAuthService _appFlowyAuthService =
|
||||
BackendAuthService(AuthTypePB.Supabase);
|
||||
BackendAuthService(AuthenticatorPB.Supabase);
|
||||
|
||||
@override
|
||||
Future<Either<FlowyError, UserProfilePB>> signUp({
|
||||
@ -67,7 +67,7 @@ class SupabaseMockAuthService implements AuthService {
|
||||
|
||||
// Create the OAuth sign-in payload.
|
||||
final payload = OauthSignInPB(
|
||||
authType: AuthTypePB.Supabase,
|
||||
authType: AuthenticatorPB.Supabase,
|
||||
map: {
|
||||
AuthServiceMapKeys.uuid: uuid,
|
||||
AuthServiceMapKeys.email: email,
|
||||
|
@ -72,8 +72,9 @@ class AnonUserItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final icon = isSelected ? const FlowySvg(FlowySvgs.check_s) : null;
|
||||
final isDisabled = isSelected || user.authType != AuthTypePB.Local;
|
||||
final desc = "${user.name}\t ${user.authType}\t";
|
||||
final isDisabled =
|
||||
isSelected || user.authenticator != AuthenticatorPB.Local;
|
||||
final desc = "${user.name}\t ${user.authenticator}\t";
|
||||
final child = SizedBox(
|
||||
height: 30,
|
||||
child: FlowyButton(
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:appflowy/core/frameless_window.dart';
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/startup/entry_point.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||
import 'package:appflowy/user/application/anon_user_bloc.dart';
|
||||
@ -101,11 +100,7 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
|
||||
}
|
||||
|
||||
Future<void> _relaunchAppAndAutoRegister() async {
|
||||
await FlowyRunner.run(
|
||||
FlowyApp(),
|
||||
integrationMode(),
|
||||
isAnon: true,
|
||||
);
|
||||
await runAppFlowy(isAnon: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ class SidebarUser extends StatelessWidget {
|
||||
Expanded(
|
||||
child: _buildUserName(context, state),
|
||||
),
|
||||
_buildSettingsButton(context, state),
|
||||
UserSettingButton(userProfile: state.userProfile),
|
||||
const HSpace(4),
|
||||
NotificationButton(views: views),
|
||||
],
|
||||
@ -64,8 +64,22 @@ class SidebarUser extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSettingsButton(BuildContext context, MenuUserState state) {
|
||||
final userProfile = state.userProfile;
|
||||
/// Return the user name, if the user name is empty, return the default user name.
|
||||
String _userName(UserProfilePB userProfile) {
|
||||
String name = userProfile.name;
|
||||
if (name.isEmpty) {
|
||||
name = LocaleKeys.defaultUsername.tr();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
class UserSettingButton extends StatelessWidget {
|
||||
final UserProfilePB userProfile;
|
||||
const UserSettingButton({required this.userProfile, super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.settings_menu_open.tr(),
|
||||
child: IconButton(
|
||||
@ -109,13 +123,4 @@ class SidebarUser extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Return the user name, if the user name is empty, return the default user name.
|
||||
String _userName(UserProfilePB userProfile) {
|
||||
String name = userProfile.name;
|
||||
if (name.isEmpty) {
|
||||
name = LocaleKeys.defaultUsername.tr();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/startup/entry_point.dart';
|
||||
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
||||
@ -207,11 +206,7 @@ class _ChangeStoragePathButtonState extends State<_ChangeStoragePathButton> {
|
||||
return;
|
||||
}
|
||||
await context.read<SettingsLocationCubit>().setCustomPath(path);
|
||||
await FlowyRunner.run(
|
||||
FlowyApp(),
|
||||
FlowyRunner.currentMode,
|
||||
isAnon: true,
|
||||
);
|
||||
await runAppFlowy(isAnon: true);
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
@ -283,11 +278,7 @@ class _RecoverDefaultStorageButtonState
|
||||
await context
|
||||
.read<SettingsLocationCubit>()
|
||||
.resetDataStoragePathToApplicationDefault();
|
||||
await FlowyRunner.run(
|
||||
FlowyApp(),
|
||||
FlowyRunner.currentMode,
|
||||
isAnon: true,
|
||||
);
|
||||
await runAppFlowy(isAnon: true);
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
@ -54,7 +54,8 @@ class SettingsUserView extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildUserIconSetting(context),
|
||||
if (isAuthEnabled && user.authType != AuthTypePB.Local) ...[
|
||||
if (isAuthEnabled &&
|
||||
user.authenticator != AuthenticatorPB.Local) ...[
|
||||
const VSpace(12),
|
||||
UserEmailInput(user.email),
|
||||
],
|
||||
@ -146,7 +147,7 @@ class SettingsUserView extends StatelessWidget {
|
||||
}
|
||||
|
||||
// If the user is logged in locally, render a third-party login button.
|
||||
if (state.userProfile.authType == AuthTypePB.Local) {
|
||||
if (state.userProfile.authenticator == AuthenticatorPB.Local) {
|
||||
return SettingThirdPartyLogin(didLogin: didLogin);
|
||||
}
|
||||
|
||||
@ -284,6 +285,7 @@ class UserNameInputState extends State<UserNameInput> {
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
_debounce?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@ -348,6 +350,7 @@ class UserEmailInputState extends State<UserEmailInput> {
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
_debounce?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class AppFlowyUnitTest {
|
||||
_pathProviderInitialized();
|
||||
|
||||
await FlowyRunner.run(
|
||||
FlowyTestApp(),
|
||||
AppFlowyApplicationUniTest(),
|
||||
IntegrationMode.unitTest,
|
||||
);
|
||||
|
||||
@ -111,7 +111,7 @@ void _pathProviderInitialized() {
|
||||
});
|
||||
}
|
||||
|
||||
class FlowyTestApp implements EntryPoint {
|
||||
class AppFlowyApplicationUniTest implements EntryPoint {
|
||||
@override
|
||||
Widget create(LaunchConfiguration config) {
|
||||
return Container();
|
||||
|
38
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
38
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
@ -139,7 +139,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
[[package]]
|
||||
name = "app-error"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"reqwest",
|
||||
@ -786,7 +786,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "client-api"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -883,7 +883,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -902,7 +902,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-database"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -932,7 +932,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -944,7 +944,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-document"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"collab",
|
||||
@ -963,7 +963,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -977,7 +977,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-folder"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@ -1019,7 +1019,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-persistence"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1040,7 +1040,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-plugins"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1066,7 +1066,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-user"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"collab",
|
||||
@ -1471,7 +1471,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
[[package]]
|
||||
name = "database-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -2842,7 +2842,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gotrue"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures-util",
|
||||
@ -2858,7 +2858,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gotrue-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -3280,7 +3280,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "infra"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"reqwest",
|
||||
@ -5040,7 +5040,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "realtime-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@ -5062,7 +5062,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "realtime-protocol"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@ -5809,7 +5809,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "shared_entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -7699,7 +7699,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "workspace-template"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -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 = "5c1a16cec52e628e2fb7648455581d6fe5e84be1" }
|
||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "80d4048c69a22c0af77b2f2e9b13b1004b2156e2" }
|
||||
# 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 = "5c1
|
||||
# To switch to the local path, run:
|
||||
# scripts/tool/update_collab_source.sh
|
||||
# ⚠️⚠️⚠️️
|
||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
|
||||
|
||||
|
||||
|
38
frontend/rust-lib/Cargo.lock
generated
38
frontend/rust-lib/Cargo.lock
generated
@ -125,7 +125,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
[[package]]
|
||||
name = "app-error"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"reqwest",
|
||||
@ -667,7 +667,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "client-api"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -733,7 +733,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -752,7 +752,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-database"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -782,7 +782,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -794,7 +794,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-document"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"collab",
|
||||
@ -813,7 +813,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -827,7 +827,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-folder"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@ -869,7 +869,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-persistence"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -890,7 +890,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-plugins"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -916,7 +916,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-user"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0e117f568bd2465762582f6aeb8d9c11fe714e63#0e117f568bd2465762582f6aeb8d9c11fe714e63"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=d5324139e6450e32246520416af768202f544869#d5324139e6450e32246520416af768202f544869"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"collab",
|
||||
@ -1277,7 +1277,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
[[package]]
|
||||
name = "database-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -2483,7 +2483,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gotrue"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures-util",
|
||||
@ -2499,7 +2499,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gotrue-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -2860,7 +2860,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "infra"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"reqwest",
|
||||
@ -4329,7 +4329,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "realtime-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@ -4351,7 +4351,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "realtime-protocol"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@ -5020,7 +5020,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "shared_entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
@ -6401,7 +6401,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "workspace-template"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5c1a16cec52e628e2fb7648455581d6fe5e84be1#5c1a16cec52e628e2fb7648455581d6fe5e84be1"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=80d4048c69a22c0af77b2f2e9b13b1004b2156e2#80d4048c69a22c0af77b2f2e9b13b1004b2156e2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -99,7 +99,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 = "5c1a16cec52e628e2fb7648455581d6fe5e84be1" }
|
||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "80d4048c69a22c0af77b2f2e9b13b1004b2156e2" }
|
||||
# Please use the following script to update collab.
|
||||
# Working directory: frontend
|
||||
#
|
||||
@ -109,11 +109,11 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5c1
|
||||
# To switch to the local path, run:
|
||||
# scripts/tool/update_collab_source.sh
|
||||
# ⚠️⚠️⚠️️
|
||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0e117f568bd2465762582f6aeb8d9c11fe714e63" }
|
||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d5324139e6450e32246520416af768202f544869" }
|
||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
||||
[lib]
|
||||
name = "dart_ffi"
|
||||
# this value will change depending on the target os
|
||||
# default staticlib
|
||||
# default static library
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ use parking_lot::RwLock;
|
||||
use flowy_core::config::AppFlowyCoreConfig;
|
||||
use flowy_core::AppFlowyCore;
|
||||
use flowy_notification::register_notification_sender;
|
||||
use flowy_user::entities::AuthTypePB;
|
||||
use flowy_user::entities::AuthenticatorPB;
|
||||
|
||||
use crate::user_event::TestNotificationSender;
|
||||
|
||||
@ -21,7 +21,7 @@ pub mod user_event;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EventIntegrationTest {
|
||||
pub auth_type: Arc<RwLock<AuthTypePB>>,
|
||||
pub auth_type: Arc<RwLock<AuthenticatorPB>>,
|
||||
pub inner: AppFlowyCore,
|
||||
#[allow(dead_code)]
|
||||
cleaner: Arc<Cleaner>,
|
||||
@ -48,7 +48,7 @@ impl EventIntegrationTest {
|
||||
|
||||
let inner = init_core(config).await;
|
||||
let notification_sender = TestNotificationSender::new();
|
||||
let auth_type = Arc::new(RwLock::new(AuthTypePB::Local));
|
||||
let auth_type = Arc::new(RwLock::new(AuthenticatorPB::Local));
|
||||
register_notification_sender(notification_sender.clone());
|
||||
std::mem::forget(inner.dispatcher());
|
||||
Self {
|
||||
|
@ -15,7 +15,7 @@ use flowy_server::supabase::define::{USER_DEVICE_ID, USER_EMAIL, USER_SIGN_IN_UR
|
||||
use flowy_server_config::af_cloud_config::AFCloudConfiguration;
|
||||
use flowy_server_config::AuthenticatorType;
|
||||
use flowy_user::entities::{
|
||||
AuthTypePB, CloudSettingPB, OauthSignInPB, SignInUrlPB, SignInUrlPayloadPB, SignUpPayloadPB,
|
||||
AuthenticatorPB, CloudSettingPB, OauthSignInPB, SignInUrlPB, SignInUrlPayloadPB, SignUpPayloadPB,
|
||||
UpdateCloudConfigPB, UpdateUserProfilePayloadPB, UserProfilePB,
|
||||
};
|
||||
use flowy_user::errors::{FlowyError, FlowyResult};
|
||||
@ -59,7 +59,7 @@ impl EventIntegrationTest {
|
||||
email,
|
||||
name: "appflowy".to_string(),
|
||||
password: password.clone(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
auth_type: AuthenticatorPB::Local,
|
||||
device_id: uuid::Uuid::new_v4().to_string(),
|
||||
}
|
||||
.into_bytes()
|
||||
@ -88,7 +88,7 @@ impl EventIntegrationTest {
|
||||
let map = third_party_sign_up_param(Uuid::new_v4().to_string());
|
||||
let payload = OauthSignInPB {
|
||||
map,
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
auth_type: AuthenticatorPB::Supabase,
|
||||
};
|
||||
|
||||
EventBuilder::new(self.clone())
|
||||
@ -106,7 +106,7 @@ impl EventIntegrationTest {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub fn set_auth_type(&self, auth_type: AuthTypePB) {
|
||||
pub fn set_auth_type(&self, auth_type: AuthenticatorPB) {
|
||||
*self.auth_type.write() = auth_type;
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ impl EventIntegrationTest {
|
||||
pub async fn af_cloud_sign_in_with_email(&self, email: &str) -> FlowyResult<UserProfilePB> {
|
||||
let payload = SignInUrlPayloadPB {
|
||||
email: email.to_string(),
|
||||
auth_type: AuthTypePB::AFCloud,
|
||||
auth_type: AuthenticatorPB::AppFlowyCloud,
|
||||
};
|
||||
let sign_in_url = EventBuilder::new(self.clone())
|
||||
.event(GenerateSignInURL)
|
||||
@ -148,7 +148,7 @@ impl EventIntegrationTest {
|
||||
map.insert(USER_DEVICE_ID.to_string(), Uuid::new_v4().to_string());
|
||||
let payload = OauthSignInPB {
|
||||
map,
|
||||
auth_type: AuthTypePB::AFCloud,
|
||||
auth_type: AuthenticatorPB::AppFlowyCloud,
|
||||
};
|
||||
|
||||
let user_profile = EventBuilder::new(self.clone())
|
||||
@ -175,7 +175,7 @@ impl EventIntegrationTest {
|
||||
);
|
||||
let payload = OauthSignInPB {
|
||||
map,
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
auth_type: AuthenticatorPB::Supabase,
|
||||
};
|
||||
|
||||
let user_profile = EventBuilder::new(self.clone())
|
||||
|
@ -1,9 +1,7 @@
|
||||
use event_integration::user_event::user_localhost_af_cloud;
|
||||
use event_integration::EventIntegrationTest;
|
||||
use flowy_core::DEFAULT_NAME;
|
||||
use flowy_user::entities::AuthTypePB;
|
||||
|
||||
use crate::util::{get_af_cloud_config, unzip_history_user_db};
|
||||
use crate::util::unzip_history_user_db;
|
||||
|
||||
#[tokio::test]
|
||||
async fn reading_039_anon_user_data_test() {
|
||||
@ -36,70 +34,43 @@ async fn reading_039_anon_user_data_test() {
|
||||
|
||||
drop(cleaner);
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn anon_user_to_af_cloud_test() {
|
||||
if get_af_cloud_config().is_none() {
|
||||
return;
|
||||
}
|
||||
let (cleaner, user_db_path) = unzip_history_user_db("./tests/asset", "039_local").unwrap();
|
||||
user_localhost_af_cloud().await;
|
||||
let test =
|
||||
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
|
||||
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)
|
||||
.await
|
||||
.child_views;
|
||||
|
||||
let user = test.af_cloud_sign_up().await;
|
||||
assert_eq!(user.auth_type, AuthTypePB::AFCloud);
|
||||
// let mut sync_state = test
|
||||
// .folder_manager
|
||||
// .get_mutex_folder()
|
||||
// .lock()
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .subscribe_sync_state();
|
||||
//
|
||||
// // TODO(nathan): will be removed when supporting merge FolderData
|
||||
// // wait until the state is SyncFinished with 10 secs timeout
|
||||
// loop {
|
||||
// select! {
|
||||
// _ = tokio::time::sleep(Duration::from_secs(10)) => {
|
||||
// panic!("Timeout waiting for sync finished");
|
||||
// }
|
||||
// state = sync_state.next() => {
|
||||
// if let Some(state) = &state {
|
||||
// if state == &SyncState::SyncFinished {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let user_first_level_views = test.get_all_workspace_views().await;
|
||||
// let user_second_level_views = test
|
||||
// .get_views(&user_first_level_views[1].id)
|
||||
// .await
|
||||
// .child_views;
|
||||
//
|
||||
// // first
|
||||
// assert_eq!(anon_first_level_views.len(), 1);
|
||||
// assert_eq!(user_first_level_views.len(), 2);
|
||||
// assert_eq!(
|
||||
// anon_first_level_views[0].name,
|
||||
// // The first one is the get started document
|
||||
// user_first_level_views[1].name
|
||||
// );
|
||||
// assert_ne!(anon_first_level_views[0].id, user_first_level_views[1].id);
|
||||
//
|
||||
// // second
|
||||
// assert_eq!(anon_second_level_views.len(), user_second_level_views.len());
|
||||
// assert_eq!(
|
||||
// anon_second_level_views[0].name,
|
||||
// user_second_level_views[0].name
|
||||
// );
|
||||
// assert_ne!(anon_second_level_views[0].id, user_second_level_views[0].id);
|
||||
drop(cleaner);
|
||||
}
|
||||
// #[tokio::test]
|
||||
// async fn migrate_anon_user_data_to_af_cloud_test() {
|
||||
// let (cleaner, user_db_path) = unzip_history_user_db("./tests/asset", "039_local").unwrap();
|
||||
// user_localhost_af_cloud().await;
|
||||
// let test =
|
||||
// EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
|
||||
// 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)
|
||||
// .await
|
||||
// .child_views;
|
||||
//
|
||||
// // The anon user data will be migrated to the AppFlowy cloud after sign up
|
||||
// let user = test.af_cloud_sign_up().await;
|
||||
// assert_eq!(user.authenticator, AuthenticatorPB::AppFlowyCloud);
|
||||
//
|
||||
// let user_first_level_views = test.get_all_workspace_views().await;
|
||||
// let user_second_level_views = test
|
||||
// .get_views(&user_first_level_views[0].id)
|
||||
// .await
|
||||
// .child_views;
|
||||
//
|
||||
// // first
|
||||
// assert_eq!(anon_first_level_views.len(), 1);
|
||||
// assert_eq!(user_first_level_views.len(), 1);
|
||||
// assert_eq!(
|
||||
// anon_first_level_views[0].name,
|
||||
// user_first_level_views[0].name
|
||||
// );
|
||||
// assert_ne!(anon_first_level_views[0].id, user_first_level_views[0].id);
|
||||
//
|
||||
// // second
|
||||
// assert_eq!(anon_second_level_views.len(), user_second_level_views.len());
|
||||
// assert_eq!(
|
||||
// anon_second_level_views[0].name,
|
||||
// user_second_level_views[0].name
|
||||
// );
|
||||
// assert_ne!(anon_second_level_views[0].id, user_second_level_views[0].id);
|
||||
// drop(cleaner);
|
||||
// }
|
||||
|
@ -1,6 +1,6 @@
|
||||
use event_integration::user_event::{login_password, unique_email};
|
||||
use event_integration::{event_builder::EventBuilder, EventIntegrationTest};
|
||||
use flowy_user::entities::{AuthTypePB, SignInPayloadPB, SignUpPayloadPB};
|
||||
use flowy_user::entities::{AuthenticatorPB, SignInPayloadPB, SignUpPayloadPB};
|
||||
use flowy_user::errors::ErrorCode;
|
||||
use flowy_user::event_map::UserEvent::*;
|
||||
|
||||
@ -14,7 +14,7 @@ async fn sign_up_with_invalid_email() {
|
||||
email: email.to_string(),
|
||||
name: valid_name(),
|
||||
password: login_password(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
auth_type: AuthenticatorPB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
@ -38,7 +38,7 @@ async fn sign_up_with_long_password() {
|
||||
email: unique_email(),
|
||||
name: valid_name(),
|
||||
password: "1234".repeat(100).as_str().to_string(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
auth_type: AuthenticatorPB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
@ -63,7 +63,7 @@ async fn sign_in_with_invalid_email() {
|
||||
email: email.to_string(),
|
||||
password: login_password(),
|
||||
name: "".to_string(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
auth_type: AuthenticatorPB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
@ -90,7 +90,7 @@ async fn sign_in_with_invalid_password() {
|
||||
email: unique_email(),
|
||||
password,
|
||||
name: "".to_string(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
auth_type: AuthenticatorPB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use nanoid::nanoid;
|
||||
|
||||
use event_integration::{event_builder::EventBuilder, EventIntegrationTest};
|
||||
use flowy_user::entities::{AuthTypePB, UpdateUserProfilePayloadPB, UserProfilePB};
|
||||
use flowy_user::entities::{AuthenticatorPB, UpdateUserProfilePayloadPB, UserProfilePB};
|
||||
use flowy_user::{errors::ErrorCode, event_map::UserEvent::*};
|
||||
|
||||
use crate::user::local_test::helper::*;
|
||||
@ -32,7 +32,7 @@ async fn anon_user_profile_get() {
|
||||
assert_eq!(user_profile.openai_key, user.openai_key);
|
||||
assert_eq!(user_profile.stability_ai_key, user.stability_ai_key);
|
||||
assert_eq!(user_profile.workspace_id, user.workspace_id);
|
||||
assert_eq!(user_profile.auth_type, AuthTypePB::Local);
|
||||
assert_eq!(user_profile.authenticator, AuthenticatorPB::Local);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -14,7 +14,9 @@ use event_integration::EventIntegrationTest;
|
||||
use flowy_core::DEFAULT_NAME;
|
||||
use flowy_encrypt::decrypt_text;
|
||||
use flowy_server::supabase::define::{USER_DEVICE_ID, USER_EMAIL, USER_UUID};
|
||||
use flowy_user::entities::{AuthTypePB, OauthSignInPB, UpdateUserProfilePayloadPB, UserProfilePB};
|
||||
use flowy_user::entities::{
|
||||
AuthenticatorPB, OauthSignInPB, UpdateUserProfilePayloadPB, UserProfilePB,
|
||||
};
|
||||
use flowy_user::errors::ErrorCode;
|
||||
use flowy_user::event_map::UserEvent::*;
|
||||
|
||||
@ -33,7 +35,7 @@ async fn third_party_sign_up_test() {
|
||||
map.insert(USER_DEVICE_ID.to_string(), uuid::Uuid::new_v4().to_string());
|
||||
let payload = OauthSignInPB {
|
||||
map,
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
auth_type: AuthenticatorPB::Supabase,
|
||||
};
|
||||
|
||||
let response = EventBuilder::new(test.clone())
|
||||
@ -77,7 +79,7 @@ async fn third_party_sign_up_with_duplicated_uuid() {
|
||||
.event(OauthSignIn)
|
||||
.payload(OauthSignInPB {
|
||||
map: map.clone(),
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
auth_type: AuthenticatorPB::Supabase,
|
||||
})
|
||||
.async_send()
|
||||
.await
|
||||
@ -88,7 +90,7 @@ async fn third_party_sign_up_with_duplicated_uuid() {
|
||||
.event(OauthSignIn)
|
||||
.payload(OauthSignInPB {
|
||||
map: map.clone(),
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
auth_type: AuthenticatorPB::Supabase,
|
||||
})
|
||||
.async_send()
|
||||
.await
|
||||
|
@ -4,7 +4,7 @@ use event_integration::{event_builder::EventBuilder, EventIntegrationTest};
|
||||
use flowy_folder2::entities::WorkspaceSettingPB;
|
||||
use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspaceSetting;
|
||||
use flowy_server::supabase::define::{USER_EMAIL, USER_UUID};
|
||||
use flowy_user::entities::{AuthTypePB, OauthSignInPB, UserProfilePB};
|
||||
use flowy_user::entities::{AuthenticatorPB, OauthSignInPB, UserProfilePB};
|
||||
use flowy_user::event_map::UserEvent::*;
|
||||
|
||||
use crate::util::*;
|
||||
@ -21,7 +21,7 @@ async fn initial_workspace_test() {
|
||||
);
|
||||
let payload = OauthSignInPB {
|
||||
map,
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
auth_type: AuthenticatorPB::Supabase,
|
||||
};
|
||||
|
||||
let _ = EventBuilder::new(test.clone())
|
||||
|
@ -23,7 +23,7 @@ use flowy_server::supabase::api::*;
|
||||
use flowy_server::{AppFlowyEncryption, EncryptionImpl};
|
||||
use flowy_server_config::af_cloud_config::AFCloudConfiguration;
|
||||
use flowy_server_config::supabase_config::SupabaseConfiguration;
|
||||
use flowy_user::entities::{AuthTypePB, UpdateUserProfilePayloadPB};
|
||||
use flowy_user::entities::{AuthenticatorPB, UpdateUserProfilePayloadPB};
|
||||
use flowy_user::errors::FlowyError;
|
||||
use flowy_user::event_map::UserCloudServiceProvider;
|
||||
use flowy_user::event_map::UserEvent::*;
|
||||
@ -43,7 +43,7 @@ impl FlowySupabaseTest {
|
||||
pub async fn new() -> Option<Self> {
|
||||
let _ = get_supabase_config()?;
|
||||
let test = EventIntegrationTest::new().await;
|
||||
test.set_auth_type(AuthTypePB::Supabase);
|
||||
test.set_auth_type(AuthenticatorPB::Supabase);
|
||||
test
|
||||
.server_provider
|
||||
.set_authenticator(Authenticator::Supabase);
|
||||
@ -210,7 +210,7 @@ impl AFCloudTest {
|
||||
pub async fn new() -> Option<Self> {
|
||||
let _ = get_af_cloud_config()?;
|
||||
let test = EventIntegrationTest::new().await;
|
||||
test.set_auth_type(AuthTypePB::AFCloud);
|
||||
test.set_auth_type(AuthenticatorPB::AppFlowyCloud);
|
||||
test
|
||||
.server_provider
|
||||
.set_authenticator(Authenticator::AppFlowyCloud);
|
||||
|
@ -22,25 +22,25 @@ pub(crate) const SERVER_PROVIDER_TYPE_KEY: &str = "server_provider_type";
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize_repr, Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum ServerType {
|
||||
pub enum Server {
|
||||
/// Local server provider.
|
||||
/// Offline mode, no user authentication and the data is stored locally.
|
||||
Local = 0,
|
||||
/// AppFlowy Cloud server provider.
|
||||
/// The [AppFlowy-Server](https://github.com/AppFlowy-IO/AppFlowy-Cloud) is still a work in
|
||||
/// progress.
|
||||
AFCloud = 1,
|
||||
AppFlowyCloud = 1,
|
||||
/// Supabase server provider.
|
||||
/// It uses supabase postgresql database to store data and user authentication.
|
||||
Supabase = 2,
|
||||
}
|
||||
|
||||
impl Display for ServerType {
|
||||
impl Display for Server {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ServerType::Local => write!(f, "Local"),
|
||||
ServerType::AFCloud => write!(f, "AppFlowyCloud"),
|
||||
ServerType::Supabase => write!(f, "Supabase"),
|
||||
Server::Local => write!(f, "Local"),
|
||||
Server::AppFlowyCloud => write!(f, "AppFlowyCloud"),
|
||||
Server::Supabase => write!(f, "Supabase"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,8 +51,8 @@ impl Display for ServerType {
|
||||
/// Each server implements the [AppFlowyServer] trait, which provides the [UserCloudService], etc.
|
||||
pub struct ServerProvider {
|
||||
config: AppFlowyCoreConfig,
|
||||
server_type: RwLock<ServerType>,
|
||||
providers: RwLock<HashMap<ServerType, Arc<dyn AppFlowyServer>>>,
|
||||
server: RwLock<Server>,
|
||||
providers: RwLock<HashMap<Server, Arc<dyn AppFlowyServer>>>,
|
||||
pub(crate) encryption: RwLock<Arc<dyn AppFlowyEncryption>>,
|
||||
pub(crate) store_preferences: Weak<StorePreferences>,
|
||||
pub(crate) enable_sync: RwLock<bool>,
|
||||
@ -62,13 +62,13 @@ pub struct ServerProvider {
|
||||
impl ServerProvider {
|
||||
pub fn new(
|
||||
config: AppFlowyCoreConfig,
|
||||
server_type: ServerType,
|
||||
server: Server,
|
||||
store_preferences: Weak<StorePreferences>,
|
||||
) -> Self {
|
||||
let encryption = EncryptionImpl::new(None);
|
||||
Self {
|
||||
config,
|
||||
server_type: RwLock::new(server_type),
|
||||
server: RwLock::new(server),
|
||||
providers: RwLock::new(HashMap::new()),
|
||||
enable_sync: RwLock::new(true),
|
||||
encryption: RwLock::new(Arc::new(encryption)),
|
||||
@ -77,37 +77,34 @@ impl ServerProvider {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_server_type(&self) -> ServerType {
|
||||
self.server_type.read().clone()
|
||||
pub fn get_server_type(&self) -> Server {
|
||||
self.server.read().clone()
|
||||
}
|
||||
|
||||
pub fn set_server_type(&self, server_type: ServerType) {
|
||||
let old_server_type = self.server_type.read().clone();
|
||||
pub fn set_server_type(&self, server_type: Server) {
|
||||
let old_server_type = self.server.read().clone();
|
||||
if server_type != old_server_type {
|
||||
self.providers.write().remove(&old_server_type);
|
||||
}
|
||||
|
||||
*self.server_type.write() = server_type;
|
||||
*self.server.write() = server_type;
|
||||
}
|
||||
|
||||
/// Returns a [AppFlowyServer] trait implementation base on the provider_type.
|
||||
pub(crate) fn get_server(
|
||||
&self,
|
||||
server_type: &ServerType,
|
||||
) -> FlowyResult<Arc<dyn AppFlowyServer>> {
|
||||
pub(crate) fn get_server(&self, server_type: &Server) -> FlowyResult<Arc<dyn AppFlowyServer>> {
|
||||
if let Some(provider) = self.providers.read().get(server_type) {
|
||||
return Ok(provider.clone());
|
||||
}
|
||||
|
||||
let server = match server_type {
|
||||
ServerType::Local => {
|
||||
Server::Local => {
|
||||
let local_db = Arc::new(LocalServerDBImpl {
|
||||
storage_path: self.config.storage_path.clone(),
|
||||
});
|
||||
let server = Arc::new(LocalServer::new(local_db));
|
||||
Ok::<Arc<dyn AppFlowyServer>, FlowyError>(server)
|
||||
},
|
||||
ServerType::AFCloud => {
|
||||
Server::AppFlowyCloud => {
|
||||
let config = AFCloudConfiguration::from_env()?;
|
||||
let server = Arc::new(AppFlowyCloudServer::new(
|
||||
config,
|
||||
@ -117,7 +114,7 @@ impl ServerProvider {
|
||||
|
||||
Ok::<Arc<dyn AppFlowyServer>, FlowyError>(server)
|
||||
},
|
||||
ServerType::Supabase => {
|
||||
Server::Supabase => {
|
||||
let config = SupabaseConfiguration::from_env()?;
|
||||
let uid = self.uid.clone();
|
||||
tracing::trace!("🔑Supabase config: {:?}", config);
|
||||
@ -140,36 +137,35 @@ impl ServerProvider {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Authenticator> for ServerType {
|
||||
impl From<Authenticator> for Server {
|
||||
fn from(auth_provider: Authenticator) -> Self {
|
||||
match auth_provider {
|
||||
Authenticator::Local => ServerType::Local,
|
||||
Authenticator::AppFlowyCloud => ServerType::AFCloud,
|
||||
Authenticator::Supabase => ServerType::Supabase,
|
||||
Authenticator::Local => Server::Local,
|
||||
Authenticator::AppFlowyCloud => Server::AppFlowyCloud,
|
||||
Authenticator::Supabase => Server::Supabase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ServerType> for Authenticator {
|
||||
fn from(ty: ServerType) -> Self {
|
||||
impl From<Server> for Authenticator {
|
||||
fn from(ty: Server) -> Self {
|
||||
match ty {
|
||||
ServerType::Local => Authenticator::Local,
|
||||
ServerType::AFCloud => Authenticator::AppFlowyCloud,
|
||||
ServerType::Supabase => Authenticator::Supabase,
|
||||
Server::Local => Authenticator::Local,
|
||||
Server::AppFlowyCloud => Authenticator::AppFlowyCloud,
|
||||
Server::Supabase => Authenticator::Supabase,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<&Authenticator> for ServerType {
|
||||
impl From<&Authenticator> for Server {
|
||||
fn from(auth_provider: &Authenticator) -> Self {
|
||||
Self::from(auth_provider.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_server_type(store_preferences: &Arc<StorePreferences>) -> ServerType {
|
||||
match store_preferences.get_object::<ServerType>(SERVER_PROVIDER_TYPE_KEY) {
|
||||
None => ServerType::Local,
|
||||
Some(provider_type) => provider_type,
|
||||
}
|
||||
pub fn current_server_type(store_preferences: &Arc<StorePreferences>) -> Server {
|
||||
store_preferences
|
||||
.get_object::<Server>(SERVER_PROVIDER_TYPE_KEY)
|
||||
.unwrap_or(Server::Local)
|
||||
}
|
||||
|
||||
struct LocalServerDBImpl {
|
||||
|
@ -30,7 +30,7 @@ use flowy_user_deps::cloud::UserCloudService;
|
||||
use flowy_user_deps::entities::{Authenticator, UserTokenState};
|
||||
use lib_infra::future::{to_fut, Fut, FutureResult};
|
||||
|
||||
use crate::integrate::server::{ServerProvider, ServerType, SERVER_PROVIDER_TYPE_KEY};
|
||||
use crate::integrate::server::{Server, ServerProvider, SERVER_PROVIDER_TYPE_KEY};
|
||||
|
||||
impl FileStorageService for ServerProvider {
|
||||
fn create_object(&self, object: StorageObject) -> FutureResult<String, FlowyError> {
|
||||
@ -91,12 +91,12 @@ impl UserCloudServiceProvider for ServerProvider {
|
||||
|
||||
/// When user login, the provider type is set by the [Authenticator] and save to disk for next use.
|
||||
///
|
||||
/// Each [Authenticator] has a corresponding [ServerType]. The [ServerType] is used
|
||||
/// to create a new [AppFlowyServer] if it doesn't exist. Once the [ServerType] is set,
|
||||
/// 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: ServerType = authenticator.into();
|
||||
let server_type: Server = authenticator.into();
|
||||
self.set_server_type(server_type.clone());
|
||||
|
||||
match self.store_preferences.upgrade() {
|
||||
@ -117,7 +117,7 @@ impl UserCloudServiceProvider for ServerProvider {
|
||||
Authenticator::from(server_type)
|
||||
}
|
||||
|
||||
/// Returns the [UserCloudService] base on the current [ServerType].
|
||||
/// 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();
|
||||
@ -127,11 +127,11 @@ impl UserCloudServiceProvider for ServerProvider {
|
||||
|
||||
fn service_url(&self) -> String {
|
||||
match self.get_server_type() {
|
||||
ServerType::Local => "".to_string(),
|
||||
ServerType::AFCloud => AFCloudConfiguration::from_env()
|
||||
Server::Local => "".to_string(),
|
||||
Server::AppFlowyCloud => AFCloudConfiguration::from_env()
|
||||
.map(|config| config.base_url)
|
||||
.unwrap_or_default(),
|
||||
ServerType::Supabase => SupabaseConfiguration::from_env()
|
||||
Server::Supabase => SupabaseConfiguration::from_env()
|
||||
.map(|config| config.url)
|
||||
.unwrap_or_default(),
|
||||
}
|
||||
@ -325,7 +325,7 @@ impl CollabStorageProvider for ServerProvider {
|
||||
collab_object,
|
||||
local_collab,
|
||||
} => {
|
||||
if let Ok(server) = self.get_server(&ServerType::AFCloud) {
|
||||
if let Ok(server) = self.get_server(&Server::AppFlowyCloud) {
|
||||
to_fut(async move {
|
||||
let mut plugins: Vec<Arc<dyn CollabPlugin>> = vec![];
|
||||
match server.collab_ws_channel(&collab_object.object_id).await {
|
||||
@ -373,7 +373,7 @@ impl CollabStorageProvider for ServerProvider {
|
||||
} => {
|
||||
let mut plugins: Vec<Arc<dyn CollabPlugin>> = vec![];
|
||||
if let Some(remote_collab_storage) = self
|
||||
.get_server(&ServerType::Supabase)
|
||||
.get_server(&Server::Supabase)
|
||||
.ok()
|
||||
.and_then(|provider| provider.collab_storage(&collab_object))
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ use crate::deps_resolve::collab_backup::RocksdbBackupImpl;
|
||||
use crate::deps_resolve::*;
|
||||
use crate::integrate::collab_interact::CollabInteractImpl;
|
||||
use crate::integrate::log::init_log;
|
||||
use crate::integrate::server::{current_server_type, ServerProvider, ServerType};
|
||||
use crate::integrate::server::{current_server_type, Server, ServerProvider};
|
||||
use crate::integrate::user::UserStatusCallbackImpl;
|
||||
|
||||
pub mod config;
|
||||
@ -232,12 +232,12 @@ fn init_user_manager(
|
||||
)
|
||||
}
|
||||
|
||||
impl From<ServerType> for CollabDataSource {
|
||||
fn from(server_type: ServerType) -> Self {
|
||||
impl From<Server> for CollabDataSource {
|
||||
fn from(server_type: Server) -> Self {
|
||||
match server_type {
|
||||
ServerType::Local => CollabDataSource::Local,
|
||||
ServerType::AFCloud => CollabDataSource::AppFlowyCloud,
|
||||
ServerType::Supabase => CollabDataSource::Supabase,
|
||||
Server::Local => CollabDataSource::Local,
|
||||
Server::AppFlowyCloud => CollabDataSource::AppFlowyCloud,
|
||||
Server::Supabase => CollabDataSource::Supabase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ use collab_document::blocks::DocumentData;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tracing::trace;
|
||||
use validator::ValidationError;
|
||||
|
||||
pub fn get_delta_for_block(block_id: &str, data: &DocumentData) -> Option<Vec<InsertDelta>> {
|
||||
|
@ -47,9 +47,6 @@ pub struct FolderManager {
|
||||
pub cloud_service: Arc<dyn FolderCloudService>,
|
||||
}
|
||||
|
||||
unsafe impl Send for FolderManager {}
|
||||
unsafe impl Sync for FolderManager {}
|
||||
|
||||
impl FolderManager {
|
||||
pub async fn new(
|
||||
user: Arc<dyn FolderUser>,
|
||||
@ -1012,8 +1009,8 @@ impl FolderManager {
|
||||
|
||||
/// Return the views that belong to the workspace. The views are filtered by the trash.
|
||||
pub(crate) fn get_workspace_view_pbs(_workspace_id: &str, folder: &Folder) -> Vec<ViewPB> {
|
||||
let trash_ids = folder
|
||||
.get_all_trash()
|
||||
let items = folder.get_all_trash();
|
||||
let trash_ids = items
|
||||
.into_iter()
|
||||
.map(|trash| trash.id)
|
||||
.collect::<Vec<String>>();
|
||||
|
@ -37,10 +37,10 @@ impl FolderManager {
|
||||
let collab_db = self.user.collab_db(uid)?;
|
||||
|
||||
let (view_tx, view_rx) = tokio::sync::broadcast::channel(100);
|
||||
let (trash_tx, trash_rx) = tokio::sync::broadcast::channel(100);
|
||||
let (section_change_tx, section_change_rx) = tokio::sync::broadcast::channel(100);
|
||||
let folder_notifier = FolderNotify {
|
||||
view_change_tx: view_tx,
|
||||
trash_change_tx: trash_tx,
|
||||
section_change_tx,
|
||||
};
|
||||
|
||||
let folder = match initial_data {
|
||||
@ -99,7 +99,7 @@ impl FolderManager {
|
||||
let weak_mutex_folder = Arc::downgrade(&self.mutex_folder);
|
||||
subscribe_folder_sync_state_changed(workspace_id.clone(), folder_state_rx, &weak_mutex_folder);
|
||||
subscribe_folder_snapshot_state_changed(workspace_id, &weak_mutex_folder);
|
||||
subscribe_folder_trash_changed(trash_rx, &weak_mutex_folder);
|
||||
subscribe_folder_trash_changed(section_change_rx, &weak_mutex_folder);
|
||||
subscribe_folder_view_changed(view_rx, &weak_mutex_folder);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ use std::sync::{Arc, Weak};
|
||||
|
||||
use collab::core::collab_state::SyncState;
|
||||
use collab_folder::{
|
||||
Folder, TrashChange, TrashChangeReceiver, View, ViewChange, ViewChangeReceiver,
|
||||
Folder, SectionChange, SectionChangeReceiver, TrashSectionChange, View, ViewChange,
|
||||
ViewChangeReceiver,
|
||||
};
|
||||
use tokio_stream::wrappers::WatchStream;
|
||||
use tokio_stream::StreamExt;
|
||||
@ -102,7 +103,7 @@ pub(crate) fn subscribe_folder_sync_state_changed(
|
||||
|
||||
/// Listen on the [TrashChange]s and notify the frontend some views were changed.
|
||||
pub(crate) fn subscribe_folder_trash_changed(
|
||||
mut rx: TrashChangeReceiver,
|
||||
mut rx: SectionChangeReceiver,
|
||||
weak_mutex_folder: &Weak<MutexFolder>,
|
||||
) {
|
||||
let weak_mutex_folder = weak_mutex_folder.clone();
|
||||
@ -111,25 +112,29 @@ pub(crate) fn subscribe_folder_trash_changed(
|
||||
if let Some(folder) = weak_mutex_folder.upgrade() {
|
||||
let mut unique_ids = HashSet::new();
|
||||
tracing::trace!("Did receive trash change: {:?}", value);
|
||||
let ids = match value {
|
||||
TrashChange::DidCreateTrash { ids } => ids,
|
||||
TrashChange::DidDeleteTrash { ids } => ids,
|
||||
};
|
||||
|
||||
if let Some(folder) = folder.lock().as_ref() {
|
||||
let views = folder.views.get_views(&ids);
|
||||
for view in views {
|
||||
unique_ids.insert(view.parent_view_id.clone());
|
||||
}
|
||||
match value {
|
||||
SectionChange::Trash(change) => {
|
||||
let ids = match change {
|
||||
TrashSectionChange::TrashItemAdded { ids } => ids,
|
||||
TrashSectionChange::TrashItemRemoved { ids } => ids,
|
||||
};
|
||||
if let Some(folder) = folder.lock().as_ref() {
|
||||
let views = folder.views.get_views(&ids);
|
||||
for view in views {
|
||||
unique_ids.insert(view.parent_view_id.clone());
|
||||
}
|
||||
|
||||
let repeated_trash: RepeatedTrashPB = folder.get_all_trash().into();
|
||||
send_notification("trash", FolderNotification::DidUpdateTrash)
|
||||
.payload(repeated_trash)
|
||||
.send();
|
||||
let repeated_trash: RepeatedTrashPB = folder.get_all_trash().into();
|
||||
send_notification("trash", FolderNotification::DidUpdateTrash)
|
||||
.payload(repeated_trash)
|
||||
.send();
|
||||
}
|
||||
|
||||
let parent_view_ids = unique_ids.into_iter().collect();
|
||||
notify_parent_view_did_change(folder.clone(), parent_view_ids);
|
||||
},
|
||||
}
|
||||
|
||||
let parent_view_ids = unique_ids.into_iter().collect();
|
||||
notify_parent_view_did_change(folder.clone(), parent_view_ids);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -54,6 +54,7 @@ impl DefaultFolderBuilder {
|
||||
views: FlattedViews::flatten_views(views),
|
||||
favorites: Default::default(),
|
||||
recent: Default::default(),
|
||||
trash: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use anyhow::Error;
|
||||
use client_api::entity::QueryCollabResult::{Failed, Success};
|
||||
use client_api::entity::{BatchQueryCollab, BatchQueryCollabParams, QueryCollabParams};
|
||||
use client_api::entity::{QueryCollab, QueryCollabParams};
|
||||
use client_api::error::ErrorCode::RecordNotFound;
|
||||
use collab::core::collab_plugin::EncodedCollabV1;
|
||||
use collab_entity::CollabType;
|
||||
@ -31,8 +31,10 @@ where
|
||||
FutureResult::new(async move {
|
||||
let params = QueryCollabParams {
|
||||
workspace_id,
|
||||
object_id,
|
||||
collab_type,
|
||||
inner: QueryCollab {
|
||||
object_id,
|
||||
collab_type,
|
||||
},
|
||||
};
|
||||
match try_get_client?.get_collab(params).await {
|
||||
Ok(data) => Ok(vec![data.doc_state.to_vec()]),
|
||||
@ -57,15 +59,13 @@ where
|
||||
let try_get_client = self.0.try_get_client();
|
||||
FutureResult::new(async move {
|
||||
let client = try_get_client?;
|
||||
let params = BatchQueryCollabParams(
|
||||
object_ids
|
||||
.into_iter()
|
||||
.map(|object_id| BatchQueryCollab {
|
||||
object_id,
|
||||
collab_type: object_ty.clone(),
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
let params = object_ids
|
||||
.into_iter()
|
||||
.map(|object_id| QueryCollab {
|
||||
object_id,
|
||||
collab_type: object_ty.clone(),
|
||||
})
|
||||
.collect();
|
||||
let results = client.batch_get_collab(&workspace_id, params).await?;
|
||||
Ok(
|
||||
results
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::Error;
|
||||
use client_api::entity::QueryCollabParams;
|
||||
use client_api::entity::{QueryCollab, QueryCollabParams};
|
||||
use collab::core::origin::CollabOrigin;
|
||||
use collab_document::document::Document;
|
||||
use collab_entity::CollabType;
|
||||
@ -27,8 +27,10 @@ where
|
||||
FutureResult::new(async move {
|
||||
let params = QueryCollabParams {
|
||||
workspace_id,
|
||||
object_id: document_id.to_string(),
|
||||
collab_type: CollabType::Document,
|
||||
inner: QueryCollab {
|
||||
object_id: document_id.to_string(),
|
||||
collab_type: CollabType::Document,
|
||||
},
|
||||
};
|
||||
let data = try_get_client?
|
||||
.get_collab(params)
|
||||
@ -60,8 +62,10 @@ where
|
||||
FutureResult::new(async move {
|
||||
let params = QueryCollabParams {
|
||||
workspace_id,
|
||||
object_id: document_id.clone(),
|
||||
collab_type: CollabType::Document,
|
||||
inner: QueryCollab {
|
||||
object_id: document_id.clone(),
|
||||
collab_type: CollabType::Document,
|
||||
},
|
||||
};
|
||||
let doc_state = try_get_client?
|
||||
.get_collab(params)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::{anyhow, Error};
|
||||
use client_api::entity::QueryCollabParams;
|
||||
use client_api::entity::{QueryCollab, QueryCollabParams};
|
||||
use collab::core::origin::CollabOrigin;
|
||||
use collab_entity::CollabType;
|
||||
|
||||
@ -60,9 +60,11 @@ where
|
||||
let try_get_client = self.0.try_get_client();
|
||||
FutureResult::new(async move {
|
||||
let params = QueryCollabParams {
|
||||
object_id: workspace_id.clone(),
|
||||
workspace_id: workspace_id.clone(),
|
||||
collab_type: CollabType::Folder,
|
||||
inner: QueryCollab {
|
||||
object_id: workspace_id.clone(),
|
||||
collab_type: CollabType::Folder,
|
||||
},
|
||||
};
|
||||
let doc_state = try_get_client?
|
||||
.get_collab(params)
|
||||
@ -98,9 +100,11 @@ where
|
||||
let try_get_client = self.0.try_get_client();
|
||||
FutureResult::new(async move {
|
||||
let params = QueryCollabParams {
|
||||
object_id: workspace_id.clone(),
|
||||
workspace_id,
|
||||
collab_type: CollabType::Folder,
|
||||
workspace_id: workspace_id.clone(),
|
||||
inner: QueryCollab {
|
||||
object_id: workspace_id,
|
||||
collab_type: CollabType::Folder,
|
||||
},
|
||||
};
|
||||
let doc_state = try_get_client?
|
||||
.get_collab(params)
|
||||
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use client_api::entity::workspace_dto::{CreateWorkspaceMember, WorkspaceMemberChangeset};
|
||||
use client_api::entity::{AFRole, AFWorkspace, AuthProvider, InsertCollabParams};
|
||||
use client_api::entity::{AFRole, AFWorkspace, AuthProvider, CollabParams, CreateCollabParams};
|
||||
use collab_entity::CollabObject;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
@ -231,16 +231,20 @@ where
|
||||
&self,
|
||||
collab_object: &CollabObject,
|
||||
data: Vec<u8>,
|
||||
override_if_exist: bool,
|
||||
) -> FutureResult<(), Error> {
|
||||
let try_get_client = self.server.try_get_client();
|
||||
let collab_object = collab_object.clone();
|
||||
FutureResult::new(async move {
|
||||
let client = try_get_client?;
|
||||
let params = InsertCollabParams::new(
|
||||
collab_object.object_id.clone(),
|
||||
collab_object.collab_type.clone(),
|
||||
data,
|
||||
let params = CreateCollabParams::new(
|
||||
collab_object.workspace_id.clone(),
|
||||
CollabParams {
|
||||
object_id: collab_object.object_id.clone(),
|
||||
encoded_collab_v1: data,
|
||||
collab_type: collab_object.collab_type.clone(),
|
||||
override_if_exist,
|
||||
},
|
||||
);
|
||||
client.create_collab(params).await?;
|
||||
Ok(())
|
||||
|
@ -141,6 +141,7 @@ impl UserCloudService for LocalServerUserAuthServiceImpl {
|
||||
&self,
|
||||
_collab_object: &CollabObject,
|
||||
_data: Vec<u8>,
|
||||
_override_if_exist: bool,
|
||||
) -> FutureResult<(), Error> {
|
||||
FutureResult::new(async { Ok(()) })
|
||||
}
|
||||
|
@ -98,12 +98,10 @@ where
|
||||
|
||||
// Query the user profile and workspaces
|
||||
tracing::debug!("user uuid: {}", params.uuid);
|
||||
let user_profile = get_user_profile(
|
||||
postgrest.clone(),
|
||||
GetUserProfileParams::Uuid(params.uuid.clone()),
|
||||
)
|
||||
.await?
|
||||
.unwrap();
|
||||
let user_profile =
|
||||
get_user_profile(postgrest.clone(), GetUserProfileParams::Uuid(params.uuid))
|
||||
.await?
|
||||
.unwrap();
|
||||
let user_workspaces = get_user_workspaces(postgrest.clone(), user_profile.uid).await?;
|
||||
let latest_workspace = user_workspaces
|
||||
.iter()
|
||||
@ -137,7 +135,7 @@ where
|
||||
FutureResult::new(async move {
|
||||
let postgrest = try_get_postgrest?;
|
||||
let params = oauth_params_from_box_any(params)?;
|
||||
let uuid = params.uuid.clone();
|
||||
let uuid = params.uuid;
|
||||
let response = get_user_profile(postgrest.clone(), GetUserProfileParams::Uuid(uuid))
|
||||
.await?
|
||||
.unwrap();
|
||||
@ -311,7 +309,8 @@ where
|
||||
fn create_collab_object(
|
||||
&self,
|
||||
collab_object: &CollabObject,
|
||||
update: Vec<u8>,
|
||||
data: Vec<u8>,
|
||||
_override_if_exist: bool,
|
||||
) -> FutureResult<(), Error> {
|
||||
let try_get_postgrest = self.server.try_get_weak_postgrest();
|
||||
let cloned_collab_object = collab_object.clone();
|
||||
@ -319,7 +318,7 @@ where
|
||||
af_spawn(async move {
|
||||
tx.send(
|
||||
async move {
|
||||
CreateCollabAction::new(cloned_collab_object, try_get_postgrest?, update)
|
||||
CreateCollabAction::new(cloned_collab_object, try_get_postgrest?, data)
|
||||
.run()
|
||||
.await?;
|
||||
Ok(())
|
||||
|
@ -141,6 +141,7 @@ pub trait UserCloudService: Send + Sync + 'static {
|
||||
&self,
|
||||
collab_object: &CollabObject,
|
||||
data: Vec<u8>,
|
||||
override_if_exist: bool,
|
||||
) -> FutureResult<(), Error>;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ use parking_lot::{Mutex, RwLock};
|
||||
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
|
||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||
use flowy_folder_deps::cloud::gen_view_id;
|
||||
use flowy_user_deps::entities::Authenticator;
|
||||
|
||||
use crate::migrations::MigrationUser;
|
||||
|
||||
@ -27,6 +28,7 @@ pub fn migration_anon_user_on_sign_up(
|
||||
old_collab_db: &Arc<RocksCollabDB>,
|
||||
new_user: &MigrationUser,
|
||||
new_collab_db: &Arc<RocksCollabDB>,
|
||||
authenticator: &Authenticator,
|
||||
) -> FlowyResult<()> {
|
||||
new_collab_db
|
||||
.with_write_txn(|new_collab_w_txn| {
|
||||
@ -72,6 +74,7 @@ pub fn migration_anon_user_on_sign_up(
|
||||
&old_collab_r_txn,
|
||||
new_user,
|
||||
new_collab_w_txn,
|
||||
authenticator,
|
||||
)?;
|
||||
|
||||
// Migrate other collab objects
|
||||
@ -191,6 +194,7 @@ fn migrate_workspace_folder<'a, 'b, W>(
|
||||
old_collab_r_txn: &'b W,
|
||||
new_user: &MigrationUser,
|
||||
new_collab_w_txn: &'a W,
|
||||
_authenticator: &Authenticator,
|
||||
) -> Result<(), PersistenceError>
|
||||
where
|
||||
'a: 'b,
|
||||
@ -206,9 +210,9 @@ where
|
||||
old_folder_collab.with_origin_transact_mut(|txn| {
|
||||
old_collab_r_txn.load_doc_with_txn(old_uid, old_workspace_id, txn)
|
||||
})?;
|
||||
let oid_user_id = UserId::from(old_uid);
|
||||
let old_user_id = UserId::from(old_uid);
|
||||
let old_folder = Folder::open(
|
||||
oid_user_id,
|
||||
old_user_id.clone(),
|
||||
Arc::new(MutexCollab::from_collab(old_folder_collab)),
|
||||
None,
|
||||
)
|
||||
@ -219,6 +223,41 @@ where
|
||||
"Can't migrate the folder data"
|
||||
)))?;
|
||||
|
||||
if let Some(old_fav_map) = folder_data.favorites.remove(&old_user_id) {
|
||||
let fav_map = old_fav_map
|
||||
.into_iter()
|
||||
.map(|mut item| {
|
||||
let new_view_id = old_to_new_id_map.get_new_id(&item.id);
|
||||
item.id = new_view_id;
|
||||
item
|
||||
})
|
||||
.collect();
|
||||
folder_data.favorites.insert(UserId::from(new_uid), fav_map);
|
||||
}
|
||||
if let Some(old_trash_map) = folder_data.trash.remove(&old_user_id) {
|
||||
let trash_map = old_trash_map
|
||||
.into_iter()
|
||||
.map(|mut item| {
|
||||
let new_view_id = old_to_new_id_map.get_new_id(&item.id);
|
||||
item.id = new_view_id;
|
||||
item
|
||||
})
|
||||
.collect();
|
||||
folder_data.trash.insert(UserId::from(new_uid), trash_map);
|
||||
}
|
||||
|
||||
if let Some(old_recent_map) = folder_data.recent.remove(&old_user_id) {
|
||||
let recent_map = old_recent_map
|
||||
.into_iter()
|
||||
.map(|mut item| {
|
||||
let new_view_id = old_to_new_id_map.get_new_id(&item.id);
|
||||
item.id = new_view_id;
|
||||
item
|
||||
})
|
||||
.collect();
|
||||
folder_data.recent.insert(UserId::from(new_uid), recent_map);
|
||||
}
|
||||
|
||||
old_to_new_id_map
|
||||
.0
|
||||
.insert(old_workspace_id.to_string(), new_workspace_id.to_string());
|
||||
|
@ -109,7 +109,7 @@ fn sync_view(
|
||||
encode_v1.len()
|
||||
);
|
||||
user_service
|
||||
.create_collab_object(&collab_object, encode_v1)
|
||||
.create_collab_object(&collab_object, encode_v1, false)
|
||||
.await?;
|
||||
},
|
||||
ViewLayout::Grid | ViewLayout::Board | ViewLayout::Calendar => {
|
||||
@ -121,7 +121,7 @@ fn sync_view(
|
||||
database_encode_v1.len()
|
||||
);
|
||||
user_service
|
||||
.create_collab_object(&collab_object, database_encode_v1)
|
||||
.create_collab_object(&collab_object, database_encode_v1, false)
|
||||
.await?;
|
||||
|
||||
// sync database's row
|
||||
@ -145,7 +145,7 @@ fn sync_view(
|
||||
);
|
||||
|
||||
let _ = user_service
|
||||
.create_collab_object(&database_row_collab_object, database_row_encode_v1)
|
||||
.create_collab_object(&database_row_collab_object, database_row_encode_v1, false)
|
||||
.await;
|
||||
|
||||
let database_row_document = CollabObject::new(
|
||||
@ -165,7 +165,7 @@ fn sync_view(
|
||||
document_encode_v1.len()
|
||||
);
|
||||
let _ = user_service
|
||||
.create_collab_object(&database_row_document, document_encode_v1)
|
||||
.create_collab_object(&database_row_document, document_encode_v1, false)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@ -271,7 +271,7 @@ async fn sync_folder(
|
||||
encode_v1.len()
|
||||
);
|
||||
if let Err(err) = user_service
|
||||
.create_collab_object(&collab_object, encode_v1)
|
||||
.create_collab_object(&collab_object, encode_v1, true)
|
||||
.await
|
||||
{
|
||||
tracing::error!("🔴sync folder failed: {:?}", err);
|
||||
@ -316,7 +316,7 @@ async fn sync_database_views(
|
||||
if let Ok((records, encode_v1)) = result {
|
||||
if let Ok(encode_v1) = encode_v1 {
|
||||
let _ = user_service
|
||||
.create_collab_object(&collab_object, encode_v1)
|
||||
.create_collab_object(&collab_object, encode_v1, false)
|
||||
.await;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ fn sync_view(
|
||||
doc_state.len()
|
||||
);
|
||||
user_service
|
||||
.create_collab_object(&collab_object, doc_state)
|
||||
.create_collab_object(&collab_object, doc_state, false)
|
||||
.await?;
|
||||
},
|
||||
ViewLayout::Grid | ViewLayout::Board | ViewLayout::Calendar => {
|
||||
@ -121,7 +121,7 @@ fn sync_view(
|
||||
database_doc_state.len()
|
||||
);
|
||||
user_service
|
||||
.create_collab_object(&collab_object, database_doc_state)
|
||||
.create_collab_object(&collab_object, database_doc_state, false)
|
||||
.await?;
|
||||
|
||||
// sync database's row
|
||||
@ -145,7 +145,7 @@ fn sync_view(
|
||||
);
|
||||
|
||||
let _ = user_service
|
||||
.create_collab_object(&database_row_collab_object, database_row_doc_state)
|
||||
.create_collab_object(&database_row_collab_object, database_row_doc_state, false)
|
||||
.await;
|
||||
|
||||
let database_row_document = CollabObject::new(
|
||||
@ -165,7 +165,7 @@ fn sync_view(
|
||||
document_doc_state.len()
|
||||
);
|
||||
let _ = user_service
|
||||
.create_collab_object(&database_row_document, document_doc_state)
|
||||
.create_collab_object(&database_row_document, document_doc_state, false)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@ -281,7 +281,7 @@ async fn sync_folder(
|
||||
update.len()
|
||||
);
|
||||
if let Err(err) = user_service
|
||||
.create_collab_object(&collab_object, update.to_vec())
|
||||
.create_collab_object(&collab_object, update.to_vec(), false)
|
||||
.await
|
||||
{
|
||||
tracing::error!("🔴sync folder failed: {:?}", err);
|
||||
@ -325,7 +325,7 @@ async fn sync_database_views(
|
||||
|
||||
if let Ok((records, doc_state)) = result {
|
||||
let _ = user_service
|
||||
.create_collab_object(&collab_object, doc_state.to_vec())
|
||||
.create_collab_object(&collab_object, doc_state.to_vec(), false)
|
||||
.await;
|
||||
records.into_iter().map(Arc::new).collect()
|
||||
} else {
|
||||
|
@ -19,7 +19,7 @@ pub struct SignInPayloadPB {
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub auth_type: AuthTypePB,
|
||||
pub auth_type: AuthenticatorPB,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub device_id: String,
|
||||
@ -53,7 +53,7 @@ pub struct SignUpPayloadPB {
|
||||
pub password: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub auth_type: AuthTypePB,
|
||||
pub auth_type: AuthenticatorPB,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub device_id: String,
|
||||
@ -88,7 +88,7 @@ pub struct OauthSignInPB {
|
||||
pub map: HashMap<String, String>,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub auth_type: AuthTypePB,
|
||||
pub auth_type: AuthenticatorPB,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default)]
|
||||
@ -97,7 +97,7 @@ pub struct SignInUrlPayloadPB {
|
||||
pub email: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub auth_type: AuthTypePB,
|
||||
pub auth_type: AuthenticatorPB,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default)]
|
||||
@ -173,13 +173,13 @@ pub struct OauthProviderDataPB {
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf_Enum, Eq, PartialEq, Debug, Clone)]
|
||||
pub enum AuthTypePB {
|
||||
pub enum AuthenticatorPB {
|
||||
Local = 0,
|
||||
Supabase = 1,
|
||||
AFCloud = 2,
|
||||
AppFlowyCloud = 2,
|
||||
}
|
||||
|
||||
impl Default for AuthTypePB {
|
||||
impl Default for AuthenticatorPB {
|
||||
fn default() -> Self {
|
||||
Self::Local
|
||||
}
|
||||
@ -232,7 +232,7 @@ impl From<UserCredentialsPB> for UserCredentials {
|
||||
#[derive(Default, ProtoBuf)]
|
||||
pub struct UserStatePB {
|
||||
#[pb(index = 1)]
|
||||
pub auth_type: AuthTypePB,
|
||||
pub auth_type: AuthenticatorPB,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Debug, Default, Clone)]
|
||||
|
@ -7,7 +7,7 @@ use flowy_user_deps::entities::*;
|
||||
|
||||
use crate::entities::parser::{UserEmail, UserIcon, UserName, UserOpenaiKey, UserPassword};
|
||||
use crate::entities::required_not_empty_str;
|
||||
use crate::entities::AuthTypePB;
|
||||
use crate::entities::AuthenticatorPB;
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
use super::parser::UserStabilityAIKey;
|
||||
@ -45,7 +45,7 @@ pub struct UserProfilePB {
|
||||
pub openai_key: String,
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub auth_type: AuthTypePB,
|
||||
pub authenticator: AuthenticatorPB,
|
||||
|
||||
#[pb(index = 8)]
|
||||
pub encryption_sign: String,
|
||||
@ -85,7 +85,7 @@ impl std::convert::From<UserProfile> for UserProfilePB {
|
||||
token: user_profile.token,
|
||||
icon_url: user_profile.icon_url,
|
||||
openai_key: user_profile.openai_key,
|
||||
auth_type: user_profile.authenticator.into(),
|
||||
authenticator: user_profile.authenticator.into(),
|
||||
encryption_sign,
|
||||
encryption_type: encryption_ty,
|
||||
workspace_id: user_profile.workspace_id,
|
||||
|
@ -114,7 +114,7 @@ impl std::default::Default for LocaleSettingsPB {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(ProtoBuf, Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct DocumentSettingsPB {
|
||||
#[pb(index = 1, one_of)]
|
||||
pub cursor_color: Option<String>,
|
||||
@ -123,15 +123,6 @@ pub struct DocumentSettingsPB {
|
||||
pub selection_color: Option<String>,
|
||||
}
|
||||
|
||||
impl std::default::Default for DocumentSettingsPB {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cursor_color: None,
|
||||
selection_color: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const APPEARANCE_DEFAULT_THEME: &str = "Default";
|
||||
pub const APPEARANCE_DEFAULT_FONT: &str = "Poppins";
|
||||
pub const APPEARANCE_DEFAULT_MONOSPACE_FONT: &str = "SF Mono";
|
||||
|
@ -35,6 +35,7 @@ use crate::migrations::document_empty_content::HistoricalEmptyDocumentMigration;
|
||||
use crate::migrations::migration::{UserDataMigration, UserLocalDataMigration};
|
||||
use crate::migrations::session_migration::migrate_session_with_user_uuid;
|
||||
use crate::migrations::workspace_and_favorite_v1::FavoriteV1AndWorkspaceArrayMigration;
|
||||
use crate::migrations::workspace_trash_v1::WorkspaceTrashMapToSectionMigration;
|
||||
use crate::migrations::MigrationUser;
|
||||
use crate::services::cloud_config::get_cloud_config;
|
||||
use crate::services::collab_interact::{CollabInteract, DefaultCollabInteract};
|
||||
@ -198,16 +199,18 @@ impl UserManager {
|
||||
let weak_pool = Arc::downgrade(&self.db_pool(user.uid)?);
|
||||
if let Some(mut token_state_rx) = self.cloud_services.subscribe_token_state() {
|
||||
event!(tracing::Level::DEBUG, "Listen token state change");
|
||||
let user_uid = user.uid;
|
||||
let user_token = user.token.clone();
|
||||
af_spawn(async move {
|
||||
while let Some(token_state) = token_state_rx.next().await {
|
||||
debug!("Token state changed: {:?}", token_state);
|
||||
match token_state {
|
||||
UserTokenState::Refresh { token } => {
|
||||
// Only save the token if the token is different from the current token
|
||||
if token != user.token {
|
||||
if token != user_token {
|
||||
if let Some(pool) = weak_pool.upgrade() {
|
||||
// Save the new token
|
||||
if let Err(err) = save_user_token(user.uid, pool, token) {
|
||||
if let Err(err) = save_user_token(user_uid, pool, token) {
|
||||
error!("Save user token failed: {}", err);
|
||||
}
|
||||
}
|
||||
@ -232,9 +235,10 @@ impl UserManager {
|
||||
let migrations: Vec<Box<dyn UserDataMigration>> = vec![
|
||||
Box::new(HistoricalEmptyDocumentMigration),
|
||||
Box::new(FavoriteV1AndWorkspaceArrayMigration),
|
||||
Box::new(WorkspaceTrashMapToSectionMigration),
|
||||
];
|
||||
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool)
|
||||
.run(migrations, ¤t_authenticator)
|
||||
.run(migrations, &user.authenticator)
|
||||
{
|
||||
Ok(applied_migrations) => {
|
||||
if !applied_migrations.is_empty() {
|
||||
@ -786,7 +790,13 @@ impl UserManager {
|
||||
) -> Result<(), FlowyError> {
|
||||
let old_collab_db = self.database.get_collab_db(old_user.session.user_id)?;
|
||||
let new_collab_db = self.database.get_collab_db(new_user.session.user_id)?;
|
||||
migration_anon_user_on_sign_up(old_user, &old_collab_db, new_user, &new_collab_db)?;
|
||||
migration_anon_user_on_sign_up(
|
||||
old_user,
|
||||
&old_collab_db,
|
||||
new_user,
|
||||
&new_collab_db,
|
||||
authenticator,
|
||||
)?;
|
||||
|
||||
match authenticator {
|
||||
Authenticator::Supabase => {
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::services::entities::Session;
|
||||
use flowy_user_deps::entities::UserProfile;
|
||||
|
||||
use crate::services::entities::Session;
|
||||
|
||||
pub mod document_empty_content;
|
||||
pub mod migration;
|
||||
pub mod session_migration;
|
||||
mod util;
|
||||
pub mod workspace_and_favorite_v1;
|
||||
pub mod workspace_trash_v1;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MigrationUser {
|
||||
|
@ -15,23 +15,21 @@ pub fn migrate_session_with_user_uuid(
|
||||
session: &Arc<parking_lot::RwLock<Option<Session>>>,
|
||||
store_preferences: &Arc<StorePreferences>,
|
||||
) {
|
||||
if !store_preferences.get_bool(MIGRATION_USER_NO_USER_UUID) {
|
||||
if store_preferences
|
||||
if !store_preferences.get_bool(MIGRATION_USER_NO_USER_UUID)
|
||||
&& store_preferences
|
||||
.set_bool(MIGRATION_USER_NO_USER_UUID, true)
|
||||
.is_ok()
|
||||
{
|
||||
if let Some(mut value) = store_preferences.get_object::<Value>(&user_config.session_cache_key)
|
||||
{
|
||||
if value.get("user_uuid").is_none() {
|
||||
value.as_object_mut().map(|map| {
|
||||
map.insert("user_uuid".to_string(), json!(Uuid::new_v4()));
|
||||
});
|
||||
{
|
||||
if let Some(mut value) = store_preferences.get_object::<Value>(&user_config.session_cache_key) {
|
||||
if value.get("user_uuid").is_none() {
|
||||
if let Some(map) = value.as_object_mut() {
|
||||
map.insert("user_uuid".to_string(), json!(Uuid::new_v4()));
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(new_session) = serde_json::from_value::<Session>(value) {
|
||||
*session.write() = Some(new_session.clone());
|
||||
let _ = store_preferences.set_object(&user_config.session_cache_key, &new_session);
|
||||
}
|
||||
if let Ok(new_session) = serde_json::from_value::<Session>(value) {
|
||||
*session.write() = Some(new_session.clone());
|
||||
let _ = store_preferences.set_object(&user_config.session_cache_key, &new_session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use collab_folder::Folder;
|
||||
use tracing::instrument;
|
||||
|
||||
use collab_integrate::{RocksCollabDB, YrsDocAction};
|
||||
use flowy_error::{internal_error, FlowyResult};
|
||||
use flowy_user_deps::entities::Authenticator;
|
||||
|
||||
use crate::migrations::migration::UserDataMigration;
|
||||
use crate::migrations::util::load_collab;
|
||||
use crate::services::entities::Session;
|
||||
|
||||
/// 1. Migrate the workspace: { trash: [view_id] } to { trash: { uid: [view_id] } }
|
||||
pub struct WorkspaceTrashMapToSectionMigration;
|
||||
|
||||
impl UserDataMigration for WorkspaceTrashMapToSectionMigration {
|
||||
fn name(&self) -> &str {
|
||||
"workspace_trash_map_to_section_migration"
|
||||
}
|
||||
|
||||
#[instrument(name = "WorkspaceTrashMapToSectionMigration", skip_all, err)]
|
||||
fn run(
|
||||
&self,
|
||||
session: &Session,
|
||||
collab_db: &Arc<RocksCollabDB>,
|
||||
_authenticator: &Authenticator,
|
||||
) -> FlowyResult<()> {
|
||||
let write_txn = collab_db.write_txn();
|
||||
if let Ok(collab) = load_collab(session.user_id, &write_txn, &session.user_workspace.id) {
|
||||
let folder = Folder::open(session.user_id, collab, None)?;
|
||||
let trash_ids = folder
|
||||
.get_trash_v1()
|
||||
.into_iter()
|
||||
.map(|fav| fav.id)
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
if !trash_ids.is_empty() {
|
||||
folder.add_trash(trash_ids);
|
||||
}
|
||||
|
||||
let encode = folder.encode_collab_v1();
|
||||
write_txn
|
||||
.flush_doc_with(
|
||||
session.user_id,
|
||||
&session.user_workspace.id,
|
||||
&encode.doc_state,
|
||||
&encode.state_vector,
|
||||
)
|
||||
.map_err(internal_error)?;
|
||||
}
|
||||
|
||||
write_txn.commit_transaction().map_err(internal_error)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ use uuid::Uuid;
|
||||
use flowy_user_deps::entities::{AuthResponse, UserProfile, UserWorkspace};
|
||||
use flowy_user_deps::entities::{Authenticator, UserAuthResponse};
|
||||
|
||||
use crate::entities::AuthTypePB;
|
||||
use crate::entities::AuthenticatorPB;
|
||||
use crate::migrations::MigrationUser;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
@ -99,7 +99,7 @@ where
|
||||
fn from(value: &T) -> Self {
|
||||
Self {
|
||||
user_id: value.user_id(),
|
||||
user_uuid: value.user_uuid().clone(),
|
||||
user_uuid: *value.user_uuid(),
|
||||
user_workspace: value.latest_workspace().clone(),
|
||||
}
|
||||
}
|
||||
@ -114,22 +114,22 @@ impl std::convert::From<Session> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuthTypePB> for Authenticator {
|
||||
fn from(pb: AuthTypePB) -> Self {
|
||||
impl From<AuthenticatorPB> for Authenticator {
|
||||
fn from(pb: AuthenticatorPB) -> Self {
|
||||
match pb {
|
||||
AuthTypePB::Supabase => Authenticator::Supabase,
|
||||
AuthTypePB::Local => Authenticator::Local,
|
||||
AuthTypePB::AFCloud => Authenticator::AppFlowyCloud,
|
||||
AuthenticatorPB::Supabase => Authenticator::Supabase,
|
||||
AuthenticatorPB::Local => Authenticator::Local,
|
||||
AuthenticatorPB::AppFlowyCloud => Authenticator::AppFlowyCloud,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Authenticator> for AuthTypePB {
|
||||
impl From<Authenticator> for AuthenticatorPB {
|
||||
fn from(auth_type: Authenticator) -> Self {
|
||||
match auth_type {
|
||||
Authenticator::Supabase => AuthTypePB::Supabase,
|
||||
Authenticator::Local => AuthTypePB::Local,
|
||||
Authenticator::AppFlowyCloud => AuthTypePB::AFCloud,
|
||||
Authenticator::Supabase => AuthenticatorPB::Supabase,
|
||||
Authenticator::Local => AuthenticatorPB::Local,
|
||||
Authenticator::AppFlowyCloud => AuthenticatorPB::AppFlowyCloud,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use tracing::subscriber::set_global_default;
|
||||
use tracing_appender::{non_blocking::WorkerGuard, rolling::RollingFileAppender};
|
||||
use tracing_bunyan_formatter::JsonStorageLayer;
|
||||
use tracing_subscriber::fmt::format::Writer;
|
||||
use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
|
||||
use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};
|
||||
|
||||
use crate::layer::FlowyFormattingLayer;
|
||||
|
||||
@ -37,22 +37,25 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> std::result::Result<(), String> {
|
||||
pub fn build(self) -> Result<(), String> {
|
||||
let env_filter = EnvFilter::new(self.env_filter);
|
||||
|
||||
let std_out_layer = fmt::layer().with_writer(std::io::stdout).pretty();
|
||||
let (non_blocking, guard) = tracing_appender::non_blocking(self.file_appender);
|
||||
let file_layer = FlowyFormattingLayer::new(non_blocking);
|
||||
|
||||
let subscriber = tracing_subscriber::fmt()
|
||||
.with_timer(CustomTime)
|
||||
.with_ansi(true)
|
||||
.with_target(false)
|
||||
.with_max_level(tracing::Level::TRACE)
|
||||
.with_thread_ids(false)
|
||||
.with_writer(std::io::stderr)
|
||||
.pretty()
|
||||
.with_env_filter(env_filter)
|
||||
.finish()
|
||||
.with(JsonStorageLayer)
|
||||
.with(FlowyFormattingLayer::new(non_blocking));
|
||||
.with(file_layer)
|
||||
.with(std_out_layer);
|
||||
|
||||
set_global_default(subscriber).map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
|
||||
# If you want to test a single file with single case, you can try this command:
|
||||
# RUST_LOG="debug" flutter test -j, --concurrency=1 'path to the file' --name 'test case name'
|
||||
# RUST_LOG="debug" flutter test -d macOS -j, 'path to the file' --name 'test case name'
|
||||
[tasks.flutter_test]
|
||||
description = "Run flutter test with single case in single file. Input: cargo make flutter_test 'path to the file' --name 'test case name'"
|
||||
script = '''
|
||||
cd appflowy_flutter
|
||||
RUST_LOG="debug" flutter test -j, --concurrency=1 "${@}"
|
||||
flutter test -j, --concurrency=1 "${@}"
|
||||
'''
|
||||
script_runner = "@shell"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user