refactor: fav and workspace (#3837)

* refactor: workspace

* chore: update collab rev

* test: add data migration test

* fix: test

* fix: tauri build

* test: fix bloc test

* test: fix bloc test

* test: fix bloc test

* chore: restore magic codde
This commit is contained in:
Nathan.fooo 2023-11-01 11:45:35 +08:00 committed by GitHub
parent 54dbcb7c5e
commit 3e088d48ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 646 additions and 661 deletions

View File

@ -53,7 +53,7 @@ void main() {
await tester.favoriteViewByName(names[1]); await tester.favoriteViewByName(names[1]);
expect( expect(
tester.findFavoritePageName(names[1]), tester.findFavoritePageName(names[1]),
findsNWidgets(2), findsNWidgets(1),
); );
await tester.unfavoriteViewByName(gettingStarted); await tester.unfavoriteViewByName(gettingStarted);
@ -131,7 +131,7 @@ void main() {
widget.view.isFavorite && widget.view.isFavorite &&
widget.categoryType == FolderCategoryType.favorite, widget.categoryType == FolderCategoryType.favorite,
), ),
findsNWidgets(6), findsNWidgets(3),
); );
await tester.hoverOnPageName( await tester.hoverOnPageName(
@ -150,7 +150,7 @@ void main() {
widget.view.isFavorite && widget.view.isFavorite &&
widget.categoryType == FolderCategoryType.favorite, widget.categoryType == FolderCategoryType.favorite,
), ),
findsNWidgets(3), findsNWidgets(2),
); );
await tester.hoverOnPageName( await tester.hoverOnPageName(

View File

@ -29,7 +29,7 @@ class MobileFavoritePageFolder extends StatelessWidget {
BlocProvider( BlocProvider(
create: (_) => MenuBloc( create: (_) => MenuBloc(
user: userProfile, user: userProfile,
workspace: workspaceSetting.workspace, workspaceId: workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()), )..add(const MenuEvent.initial()),
), ),
BlocProvider( BlocProvider(

View File

@ -19,7 +19,7 @@ class MobileFavoriteScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return FutureBuilder(
future: Future.wait([ future: Future.wait([
FolderEventGetCurrentWorkspace().send(), FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(), getIt<AuthService>().getUser(),
]), ]),
builder: (context, snapshots) { builder: (context, snapshots) {

View File

@ -29,7 +29,7 @@ class MobileFolders extends StatelessWidget {
BlocProvider( BlocProvider(
create: (_) => MenuBloc( create: (_) => MenuBloc(
user: user, user: user,
workspace: workspaceSetting.workspace, workspaceId: workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()), )..add(const MenuEvent.initial()),
), ),
BlocProvider( BlocProvider(

View File

@ -24,7 +24,7 @@ class MobileHomeScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return FutureBuilder(
future: Future.wait([ future: Future.wait([
FolderEventGetCurrentWorkspace().send(), FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(), getIt<AuthService>().getUser(),
]), ]),
builder: (context, snapshots) { builder: (context, snapshots) {

View File

@ -90,14 +90,14 @@ class UserBackendService {
} }
Future<Either<List<WorkspacePB>, FlowyError>> getWorkspaces() { Future<Either<List<WorkspacePB>, FlowyError>> getWorkspaces() {
final request = WorkspaceIdPB.create(); // final request = WorkspaceIdPB.create();
// return FolderEventReadAllWorkspaces(request).send().then((result) {
return FolderEventReadAllWorkspaces(request).send().then((result) { // return result.fold(
return result.fold( // (workspaces) => left(workspaces.items),
(workspaces) => left(workspaces.items), // (error) => right(error),
(error) => right(error), // );
); // });
}); return Future.value(left([]));
} }
Future<Either<WorkspacePB, FlowyError>> openWorkspace(String workspaceId) { Future<Either<WorkspacePB, FlowyError>> openWorkspace(String workspaceId) {
@ -110,6 +110,15 @@ class UserBackendService {
}); });
} }
Future<Either<WorkspacePB, FlowyError>> getCurrentWorkspace() {
return FolderEventReadCurrentWorkspace().send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
Future<Either<WorkspacePB, FlowyError>> createWorkspace( Future<Either<WorkspacePB, FlowyError>> createWorkspace(
String name, String name,
String desc, String desc,

View File

@ -42,7 +42,7 @@ class AuthRouter {
BuildContext context, BuildContext context,
UserProfilePB userProfile, UserProfilePB userProfile,
) async { ) async {
final result = await FolderEventGetCurrentWorkspace().send(); final result = await FolderEventGetCurrentWorkspaceSetting().send();
result.fold( result.fold(
(workspaceSetting) { (workspaceSetting) {
// Replace SignInScreen or SkipLogInScreen as root page. // Replace SignInScreen or SkipLogInScreen as root page.
@ -104,7 +104,7 @@ class SplashRouter {
}, },
); );
FolderEventGetCurrentWorkspace().send().then((result) { FolderEventGetCurrentWorkspaceSetting().send().then((result) {
result.fold( result.fold(
(workspaceSettingPB) => pushHomeScreen(context), (workspaceSettingPB) => pushHomeScreen(context),
(r) => null, (r) => null,

View File

@ -75,7 +75,7 @@ class SplashScreen extends StatelessWidget {
if (check.requireSecret) { if (check.requireSecret) {
getIt<AuthRouter>().pushEncryptionScreen(context, userProfile); getIt<AuthRouter>().pushEncryptionScreen(context, userProfile);
} else { } else {
final result = await FolderEventGetCurrentWorkspace().send(); final result = await FolderEventGetCurrentWorkspaceSetting().send();
result.fold( result.fold(
(workspaceSetting) { (workspaceSetting) {
// After login, replace Splash screen by corresponding home screen // After login, replace Splash screen by corresponding home screen

View File

@ -41,8 +41,8 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
emit(state.copyWith(isLoading: e.isLoading)); emit(state.copyWith(isLoading: e.isLoading));
}, },
didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) { didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) {
final latestView = workspaceSetting.hasLatestView() final latestView = value.setting.hasLatestView()
? workspaceSetting.latestView ? value.setting.latestView
: state.latestView; : state.latestView;
emit( emit(

View File

@ -5,7 +5,6 @@ import 'package:appflowy/workspace/application/workspace/workspace_service.dart'
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -17,17 +16,17 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
final WorkspaceService _workspaceService; final WorkspaceService _workspaceService;
final WorkspaceListener _listener; final WorkspaceListener _listener;
final UserProfilePB user; final UserProfilePB user;
final WorkspacePB workspace; final String workspaceId;
MenuBloc({ MenuBloc({
required this.user, required this.user,
required this.workspace, required this.workspaceId,
}) : _workspaceService = WorkspaceService(workspaceId: workspace.id), }) : _workspaceService = WorkspaceService(workspaceId: workspaceId),
_listener = WorkspaceListener( _listener = WorkspaceListener(
user: user, user: user,
workspaceId: workspace.id, workspaceId: workspaceId,
), ),
super(MenuState.initial(workspace)) { super(MenuState.initial()) {
on<MenuEvent>((event, emit) async { on<MenuEvent>((event, emit) async {
await event.map( await event.map(
initial: (e) async { initial: (e) async {
@ -122,8 +121,8 @@ class MenuState with _$MenuState {
ViewPB? lastCreatedView, ViewPB? lastCreatedView,
}) = _MenuState; }) = _MenuState;
factory MenuState.initial(WorkspacePB workspace) => MenuState( factory MenuState.initial() => MenuState(
views: workspace.views, views: [],
successOrFailure: left(unit), successOrFailure: left(unit),
lastCreatedView: null, lastCreatedView: null,
); );

View File

@ -200,10 +200,10 @@ class ViewBackendService {
Future<List<ViewPB>> fetchViews() async { Future<List<ViewPB>> fetchViews() async {
final result = <ViewPB>[]; final result = <ViewPB>[];
return FolderEventGetCurrentWorkspace().send().then((value) async { return FolderEventReadCurrentWorkspace().send().then((value) async {
final workspaces = value.getLeftOrNull<WorkspaceSettingPB>(); final workspace = value.getLeftOrNull<WorkspacePB>();
if (workspaces != null) { if (workspace != null) {
final views = workspaces.workspace.views; final views = workspace.views;
for (final view in views) { for (final view in views) {
result.add(view); result.add(view);
final childViews = await getAllViews(view); final childViews = await getAllViews(view);

View File

@ -1,15 +1,12 @@
import 'dart:async'; import 'dart:async';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart' import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'
show CreateViewPayloadPB, MoveViewPayloadPB, ViewLayoutPB, ViewPB; show CreateViewPayloadPB, MoveViewPayloadPB, ViewLayoutPB, ViewPB;
import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
class WorkspaceService { class WorkspaceService {
final String workspaceId; final String workspaceId;
WorkspaceService({ WorkspaceService({
@ -38,24 +35,7 @@ class WorkspaceService {
} }
Future<Either<WorkspacePB, FlowyError>> getWorkspace() { Future<Either<WorkspacePB, FlowyError>> getWorkspace() {
final payload = WorkspaceIdPB.create()..value = workspaceId; return FolderEventReadCurrentWorkspace().send();
return FolderEventReadAllWorkspaces(payload).send().then((result) {
return result.fold(
(workspaces) {
assert(workspaces.items.length == 1);
if (workspaces.items.isEmpty) {
return right(
FlowyError.create()
..msg = LocaleKeys.workspace_notFoundError.tr(),
);
} else {
return left(workspaces.items[0]);
}
},
(error) => right(error),
);
});
} }
Future<Either<List<ViewPB>, FlowyError>> getViews() { Future<Either<List<ViewPB>, FlowyError>> getViews() {

View File

@ -39,7 +39,7 @@ class DesktopHomeScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return FutureBuilder(
future: Future.wait([ future: Future.wait([
FolderEventGetCurrentWorkspace().send(), FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(), getIt<AuthService>().getUser(),
]), ]),
builder: (context, snapshots) { builder: (context, snapshots) {

View File

@ -46,7 +46,7 @@ class HomeSideBar extends StatelessWidget {
BlocProvider( BlocProvider(
create: (_) => MenuBloc( create: (_) => MenuBloc(
user: user, user: user,
workspace: workspaceSetting.workspace, workspaceId: workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()), )..add(const MenuEvent.initial()),
), ),
BlocProvider( BlocProvider(

View File

@ -33,14 +33,14 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder<dartz.Either<WorkspaceSettingPB, FlowyError>>( return FutureBuilder<dartz.Either<WorkspacePB, FlowyError>>(
future: FolderEventGetCurrentWorkspace().send(), future: FolderEventReadCurrentWorkspace().send(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData && if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) { snapshot.connectionState == ConnectionState.done) {
final workspaces = snapshot.data?.getLeftOrNull<WorkspaceSettingPB>(); final workspace = snapshot.data?.getLeftOrNull<WorkspacePB>();
if (workspaces != null) { if (workspace != null) {
final views = workspaces.workspace.views; final views = workspace.views;
cubit ??= SettingsFileExporterCubit(views: views); cubit ??= SettingsFileExporterCubit(views: views);
return BlocProvider<SettingsFileExporterCubit>.value( return BlocProvider<SettingsFileExporterCubit>.value(
value: cubit!, value: cubit!,

View File

@ -126,7 +126,7 @@ void main() {
..add(const DocumentEvent.initial()); ..add(const DocumentEvent.initial());
await blocResponseFuture(); await blocResponseFuture();
final workspaceSetting = await FolderEventGetCurrentWorkspace() final workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send() .send()
.then((result) => result.fold((l) => l, (r) => throw Exception())); .then((result) => result.fold((l) => l, (r) => throw Exception()));
workspaceSetting.latestView.id == document1.id; workspaceSetting.latestView.id == document1.id;
@ -147,7 +147,7 @@ void main() {
final grid = bloc.state.latestCreatedView; final grid = bloc.state.latestCreatedView;
assert(grid!.name == "grid 2"); assert(grid!.name == "grid 2");
var workspaceSetting = await FolderEventGetCurrentWorkspace() var workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send() .send()
.then((result) => result.fold((l) => l, (r) => throw Exception())); .then((result) => result.fold((l) => l, (r) => throw Exception()));
workspaceSetting.latestView.id == grid!.id; workspaceSetting.latestView.id == grid!.id;
@ -158,7 +158,7 @@ void main() {
..add(const DocumentEvent.initial()); ..add(const DocumentEvent.initial());
await blocResponseFuture(); await blocResponseFuture();
workspaceSetting = await FolderEventGetCurrentWorkspace() workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send() .send()
.then((result) => result.fold((l) => l, (r) => throw Exception())); .then((result) => result.fold((l) => l, (r) => throw Exception()));
workspaceSetting.latestView.id == document.id; workspaceSetting.latestView.id == document.id;

View File

@ -14,7 +14,7 @@ void main() {
}); });
test('initi home screen', () async { test('initi home screen', () async {
final workspaceSetting = await FolderEventGetCurrentWorkspace() final workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send() .send()
.then((result) => result.fold((l) => l, (r) => throw Exception())); .then((result) => result.fold((l) => l, (r) => throw Exception()));
await blocResponseFuture(); await blocResponseFuture();
@ -27,7 +27,7 @@ void main() {
}); });
test('open the document', () async { test('open the document', () async {
final workspaceSetting = await FolderEventGetCurrentWorkspace() final workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send() .send()
.then((result) => result.fold((l) => l, (r) => throw Exception())); .then((result) => result.fold((l) => l, (r) => throw Exception()));
await blocResponseFuture(); await blocResponseFuture();
@ -52,6 +52,7 @@ void main() {
await FolderEventSetLatestView(ViewIdPB(value: latestView.id)).send(); await FolderEventSetLatestView(ViewIdPB(value: latestView.id)).send();
await blocResponseFuture(); await blocResponseFuture();
assert(homeBloc.state.workspaceSetting.latestView.id == latestView.id); final actual = homeBloc.state.workspaceSetting.latestView.id;
assert(actual == latestView.id);
}); });
} }

View File

@ -12,7 +12,7 @@ void main() {
test('assert initial apps is the build-in app', () async { test('assert initial apps is the build-in app', () async {
final menuBloc = MenuBloc( final menuBloc = MenuBloc(
user: testContext.userProfile, user: testContext.userProfile,
workspace: testContext.currentWorkspace, workspaceId: testContext.currentWorkspace.id,
)..add(const MenuEvent.initial()); )..add(const MenuEvent.initial());
await blocResponseFuture(); await blocResponseFuture();
@ -22,7 +22,7 @@ void main() {
test('reorder apps', () async { test('reorder apps', () async {
final menuBloc = MenuBloc( final menuBloc = MenuBloc(
user: testContext.userProfile, user: testContext.userProfile,
workspace: testContext.currentWorkspace, workspaceId: testContext.currentWorkspace.id,
)..add(const MenuEvent.initial()); )..add(const MenuEvent.initial());
await blocResponseFuture(); await blocResponseFuture();
menuBloc.add(const MenuEvent.createApp("App 1")); menuBloc.add(const MenuEvent.createApp("App 1"));

View File

@ -27,7 +27,7 @@ class AppFlowyUnitTest {
late UserProfilePB userProfile; late UserProfilePB userProfile;
late UserBackendService userService; late UserBackendService userService;
late WorkspaceService workspaceService; late WorkspaceService workspaceService;
late List<WorkspacePB> workspaces; late WorkspacePB workspace;
static Future<AppFlowyUnitTest> ensureInitialized() async { static Future<AppFlowyUnitTest> ensureInitialized() async {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
@ -68,12 +68,12 @@ class AppFlowyUnitTest {
); );
} }
WorkspacePB get currentWorkspace => workspaces[0]; WorkspacePB get currentWorkspace => workspace;
Future<void> _loadWorkspace() async { Future<void> _loadWorkspace() async {
final result = await userService.getWorkspaces(); final result = await userService.getCurrentWorkspace();
result.fold( result.fold(
(value) => workspaces = value, (value) => workspace = value,
(error) { (error) {
throw Exception(error); throw Exception(error);
}, },

View File

@ -445,7 +445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [ dependencies = [
"borsh-derive", "borsh-derive",
"hashbrown 0.13.2", "hashbrown 0.12.3",
] ]
[[package]] [[package]]
@ -845,7 +845,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -864,7 +864,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -894,7 +894,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-derive" name = "collab-derive"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -906,7 +906,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -926,7 +926,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -940,7 +940,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -982,7 +982,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-persistence" name = "collab-persistence"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bincode", "bincode",
@ -1003,7 +1003,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1030,7 +1030,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",

View File

@ -48,14 +48,14 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c87
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }

View File

@ -2,9 +2,9 @@ import { currentUserActions } from '../../stores/reducers/current-user/slice';
import { useAppDispatch, useAppSelector } from '../../stores/store'; import { useAppDispatch, useAppSelector } from '../../stores/store';
import { UserProfilePB } from '../../../services/backend/events/flowy-user'; import { UserProfilePB } from '../../../services/backend/events/flowy-user';
import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc'; import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
import { FolderEventGetCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace'; import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace';
import { Log } from '../../utils/log'; import { Log } from '../../utils/log';
import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder2';
export const useAuth = () => { export const useAuth = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -99,7 +99,7 @@ export const useAuth = () => {
} }
async function _openWorkspace() { async function _openWorkspace() {
return FolderEventGetCurrentWorkspace(); return FolderEventGetCurrentWorkspaceSetting();
} }
return { currentUser, checkUser, register, login, logout }; return { currentUser, checkUser, register, login, logout };

View File

@ -6,7 +6,6 @@ import {
ViewPB, ViewPB,
WorkspaceSettingPB, WorkspaceSettingPB,
} from '../../../services/backend'; } from '../../../services/backend';
import { FolderEventGetCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
import { DatabaseController } from '../../stores/effects/database/database_controller'; import { DatabaseController } from '../../stores/effects/database/database_controller';
import { RowInfo } from '../../stores/effects/database/row/row_cache'; import { RowInfo } from '../../stores/effects/database/row/row_cache';
import { RowController } from '../../stores/effects/database/row/row_controller'; import { RowController } from '../../stores/effects/database/row/row_controller';
@ -28,12 +27,15 @@ import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database
import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc'; import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc';
import { Log } from '$app/utils/log'; import { Log } from '$app/utils/log';
import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller'; import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller';
import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder2';
// Create a database page for specific layout type // Create a database page for specific layout type
// Do not use it production code. Just for testing // Do not use it production code. Just for testing
export async function createTestDatabaseView(layout: ViewLayoutPB): Promise<ViewPB> { export async function createTestDatabaseView(layout: ViewLayoutPB): Promise<ViewPB> {
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspace().then((result) => result.unwrap()); const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspaceSetting().then((result) =>
const wsSvc = new WorkspaceController(workspaceSetting.workspace.id); result.unwrap()
);
const wsSvc = new WorkspaceController(workspaceSetting.workspace_id);
const viewRes = await wsSvc.createView({ name: 'New Grid', layout }); const viewRes = await wsSvc.createView({ name: 'New Grid', layout });
return viewRes; return viewRes;

View File

@ -1,10 +1,12 @@
import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend'; import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend';
import { FolderEventGetCurrentWorkspace } from '@/services/backend/events/flowy-folder2';
import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller'; import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller';
import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder2';
export async function createTestDocument() { export async function createTestDocument() {
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspace().then((result) => result.unwrap()); const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspaceSetting().then((result) =>
const appService = new WorkspaceController(workspaceSetting.workspace.id); result.unwrap()
);
const appService = new WorkspaceController(workspaceSetting.workspace_id);
const result = await appService.createView({ name: 'New Document', layout: ViewLayoutPB.Document }); const result = await appService.createView({ name: 'New Document', layout: ViewLayoutPB.Document });
return result; return result;

View File

@ -18,9 +18,8 @@ const testCreateFolder = async (userId?: number) => {
console.log('workspaces: ', workspaces.val.toObject()); console.log('workspaces: ', workspaces.val.toObject());
} }
const currentWorkspace = await userBackendService.getCurrentWorkspace(); const currentWorkspaceSetting = await userBackendService.getCurrentWorkspaceSetting();
const workspaceService = new WorkspaceController(currentWorkspaceSetting.workspace_id);
const workspaceService = new WorkspaceController(currentWorkspace.workspace.id);
const rootViews: ViewPB[] = []; const rootViews: ViewPB[] = [];
for (let i = 1; i <= 3; i++) { for (let i = 1; i <= 3; i++) {

View File

@ -25,8 +25,8 @@ import {
import { import {
FolderEventCreateWorkspace, FolderEventCreateWorkspace,
FolderEventOpenWorkspace, FolderEventOpenWorkspace,
FolderEventGetCurrentWorkspace, FolderEventGetCurrentWorkspaceSetting,
FolderEventReadAllWorkspaces, FolderEventReadCurrentWorkspace,
} from '@/services/backend/events/flowy-folder2'; } from '@/services/backend/events/flowy-folder2';
export class UserBackendService { export class UserBackendService {
@ -56,8 +56,8 @@ export class UserBackendService {
return UserEventUpdateUserProfile(payload); return UserEventUpdateUserProfile(payload);
}; };
getCurrentWorkspace = async (): Promise<WorkspaceSettingPB> => { getCurrentWorkspaceSetting = async (): Promise<WorkspaceSettingPB> => {
const result = await FolderEventGetCurrentWorkspace(); const result = await FolderEventGetCurrentWorkspaceSetting();
if (result.ok) { if (result.ok) {
return result.val; return result.val;
@ -67,14 +67,11 @@ export class UserBackendService {
}; };
getWorkspaces = () => { getWorkspaces = () => {
const payload = WorkspaceIdPB.fromObject({}); return FolderEventReadCurrentWorkspace();
return FolderEventReadAllWorkspaces(payload);
}; };
openWorkspace = (workspaceId: string) => { openWorkspace = (workspaceId: string) => {
const payload = WorkspaceIdPB.fromObject({ value: workspaceId }); const payload = WorkspaceIdPB.fromObject({ value: workspaceId });
return FolderEventOpenWorkspace(payload); return FolderEventOpenWorkspace(payload);
}; };
@ -115,9 +112,14 @@ export class AuthBackendService {
return UserEventSignIn(payload); return UserEventSignIn(payload);
}; };
signUp = (params: { name: string; email: string; password: string; }) => { signUp = (params: { name: string; email: string; password: string }) => {
const deviceId = nanoid(8); const deviceId = nanoid(8);
const payload = SignUpPayloadPB.fromObject({ name: params.name, email: params.email, password: params.password, device_id: deviceId }); const payload = SignUpPayloadPB.fromObject({
name: params.name,
email: params.email,
password: params.password,
device_id: deviceId,
});
return UserEventSignUp(payload); return UserEventSignUp(payload);
}; };

View File

@ -1,12 +1,11 @@
import { import {
FolderEventCreateWorkspace, FolderEventCreateWorkspace,
FolderEventGetCurrentWorkspace,
CreateWorkspacePayloadPB, CreateWorkspacePayloadPB,
FolderEventReadAllWorkspaces,
FolderEventOpenWorkspace, FolderEventOpenWorkspace,
FolderEventDeleteWorkspace, FolderEventDeleteWorkspace,
WorkspaceIdPB, WorkspaceIdPB,
FolderEventReadWorkspaceViews, FolderEventReadWorkspaceViews,
FolderEventReadCurrentWorkspace,
} from '@/services/backend/events/flowy-folder2'; } from '@/services/backend/events/flowy-folder2';
export class WorkspaceBackendService { export class WorkspaceBackendService {
@ -41,14 +40,11 @@ export class WorkspaceBackendService {
}; };
getWorkspaces = async () => { getWorkspaces = async () => {
// if workspaceId is not provided, it will return all workspaces return FolderEventReadCurrentWorkspace();
const workspaceId = new WorkspaceIdPB();
return FolderEventReadAllWorkspaces(workspaceId);
}; };
getCurrentWorkspace = async () => { getCurrentWorkspace = async () => {
return FolderEventGetCurrentWorkspace(); return FolderEventReadCurrentWorkspace();
}; };
getChildPages = async (workspaceId: string) => { getChildPages = async (workspaceId: string) => {

View File

@ -33,14 +33,14 @@ export class WorkspaceManagerController {
const result = await this.backendService.getWorkspaces(); const result = await this.backendService.getWorkspaces();
if (result.ok) { if (result.ok) {
const items = result.val.items; const item = result.val;
return items.map((item) => { return [
return { {
id: item.id, id: item.id,
name: item.name, name: item.name,
}; },
}); ];
} }
return []; return [];
@ -50,8 +50,7 @@ export class WorkspaceManagerController {
const result = await this.backendService.getCurrentWorkspace(); const result = await this.backendService.getCurrentWorkspace();
if (result.ok) { if (result.ok) {
const workspace = result.val.workspace; const workspace = result.val;
return { return {
id: workspace.id, id: workspace.id,
name: workspace.name, name: workspace.name,

View File

@ -452,7 +452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [ dependencies = [
"borsh-derive", "borsh-derive",
"hashbrown 0.13.2", "hashbrown 0.12.3",
] ]
[[package]] [[package]]
@ -712,7 +712,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -731,7 +731,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -761,7 +761,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-derive" name = "collab-derive"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -773,7 +773,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -793,7 +793,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -807,7 +807,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -849,7 +849,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-persistence" name = "collab-persistence"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bincode", "bincode",
@ -870,7 +870,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -897,7 +897,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",

View File

@ -92,11 +92,11 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c87
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" } collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }

View File

@ -37,7 +37,7 @@ impl DocumentEventTest {
pub async fn create_document(&self) -> ViewPB { pub async fn create_document(&self) -> ViewPB {
let core = &self.inner; let core = &self.inner;
let current_workspace = core.get_current_workspace().await.workspace; let current_workspace = core.get_current_workspace().await;
let parent_id = current_workspace.id.clone(); let parent_id = current_workspace.id.clone();
let payload = CreateViewPayloadPB { let payload = CreateViewPayloadPB {

View File

@ -47,12 +47,12 @@ impl EventIntegrationTest {
.items .items
} }
pub async fn get_current_workspace(&self) -> WorkspaceSettingPB { pub async fn get_current_workspace(&self) -> WorkspacePB {
EventBuilder::new(self.clone()) EventBuilder::new(self.clone())
.event(FolderEvent::GetCurrentWorkspace) .event(FolderEvent::ReadCurrentWorkspace)
.async_send() .async_send()
.await .await
.parse::<WorkspaceSettingPB>() .parse::<WorkspacePB>()
} }
pub async fn get_all_workspace_views(&self) -> Vec<ViewPB> { pub async fn get_all_workspace_views(&self) -> Vec<ViewPB> {
@ -148,9 +148,9 @@ pub struct ViewTest {
impl ViewTest { impl ViewTest {
#[allow(dead_code)] #[allow(dead_code)]
pub async fn new(sdk: &EventIntegrationTest, layout: ViewLayoutPB, data: Vec<u8>) -> Self { pub async fn new(sdk: &EventIntegrationTest, layout: ViewLayoutPB, data: Vec<u8>) -> Self {
let workspace = create_workspace(sdk, "Workspace", "").await; let workspace = sdk.folder_manager.get_current_workspace().await.unwrap();
let payload = WorkspaceIdPB { let payload = WorkspaceIdPB {
value: Some(workspace.id.clone()), value: workspace.id.clone(),
}; };
let _ = EventBuilder::new(sdk.clone()) let _ = EventBuilder::new(sdk.clone())
.event(OpenWorkspace) .event(OpenWorkspace)
@ -196,6 +196,7 @@ impl ViewTest {
} }
} }
#[allow(dead_code)]
async fn create_workspace(sdk: &EventIntegrationTest, name: &str, desc: &str) -> WorkspacePB { async fn create_workspace(sdk: &EventIntegrationTest, name: &str, desc: &str) -> WorkspacePB {
let request = CreateWorkspacePayloadPB { let request = CreateWorkspacePayloadPB {
name: name.to_owned(), name: name.to_owned(),

View File

@ -14,7 +14,7 @@ use lib_infra::util::timestamp;
#[tokio::test] #[tokio::test]
async fn get_database_id_event_test() { async fn get_database_id_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -36,7 +36,7 @@ async fn get_database_id_event_test() {
#[tokio::test] #[tokio::test]
async fn get_database_event_test() { async fn get_database_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -50,7 +50,7 @@ async fn get_database_event_test() {
#[tokio::test] #[tokio::test]
async fn get_field_event_test() { async fn get_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -65,7 +65,7 @@ async fn get_field_event_test() {
#[tokio::test] #[tokio::test]
async fn create_field_event_test() { async fn create_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -79,7 +79,7 @@ async fn create_field_event_test() {
#[tokio::test] #[tokio::test]
async fn delete_field_event_test() { async fn delete_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -100,7 +100,7 @@ async fn delete_field_event_test() {
#[tokio::test] #[tokio::test]
async fn delete_primary_field_event_test() { async fn delete_primary_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -115,7 +115,7 @@ async fn delete_primary_field_event_test() {
#[tokio::test] #[tokio::test]
async fn update_field_type_event_test() { async fn update_field_type_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -133,7 +133,7 @@ async fn update_field_type_event_test() {
#[tokio::test] #[tokio::test]
async fn update_primary_field_type_event_test() { async fn update_primary_field_type_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -152,7 +152,7 @@ async fn update_primary_field_type_event_test() {
#[tokio::test] #[tokio::test]
async fn duplicate_field_event_test() { async fn duplicate_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -170,7 +170,7 @@ async fn duplicate_field_event_test() {
#[tokio::test] #[tokio::test]
async fn duplicate_primary_field_test() { async fn duplicate_primary_field_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -184,7 +184,7 @@ async fn duplicate_primary_field_test() {
#[tokio::test] #[tokio::test]
async fn get_primary_field_event_test() { async fn get_primary_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -197,7 +197,7 @@ async fn get_primary_field_event_test() {
#[tokio::test] #[tokio::test]
async fn create_row_event_test() { async fn create_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -210,7 +210,7 @@ async fn create_row_event_test() {
#[tokio::test] #[tokio::test]
async fn delete_row_event_test() { async fn delete_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -233,7 +233,7 @@ async fn delete_row_event_test() {
#[tokio::test] #[tokio::test]
async fn get_row_event_test() { async fn get_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -249,7 +249,7 @@ async fn get_row_event_test() {
#[tokio::test] #[tokio::test]
async fn update_row_meta_event_with_url_test() { async fn update_row_meta_event_with_url_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -277,7 +277,7 @@ async fn update_row_meta_event_with_url_test() {
#[tokio::test] #[tokio::test]
async fn update_row_meta_event_with_cover_test() { async fn update_row_meta_event_with_cover_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -305,7 +305,7 @@ async fn update_row_meta_event_with_cover_test() {
#[tokio::test] #[tokio::test]
async fn delete_row_event_with_invalid_row_id_test() { async fn delete_row_event_with_invalid_row_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -318,7 +318,7 @@ async fn delete_row_event_with_invalid_row_id_test() {
#[tokio::test] #[tokio::test]
async fn duplicate_row_event_test() { async fn duplicate_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -335,7 +335,7 @@ async fn duplicate_row_event_test() {
#[tokio::test] #[tokio::test]
async fn duplicate_row_event_with_invalid_row_id_test() { async fn duplicate_row_event_with_invalid_row_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -352,7 +352,7 @@ async fn duplicate_row_event_with_invalid_row_id_test() {
#[tokio::test] #[tokio::test]
async fn move_row_event_test() { async fn move_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -372,7 +372,7 @@ async fn move_row_event_test() {
#[tokio::test] #[tokio::test]
async fn move_row_event_test2() { async fn move_row_event_test2() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -392,7 +392,7 @@ async fn move_row_event_test2() {
#[tokio::test] #[tokio::test]
async fn move_row_event_with_invalid_row_id_test() { async fn move_row_event_with_invalid_row_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -419,7 +419,7 @@ async fn move_row_event_with_invalid_row_id_test() {
#[tokio::test] #[tokio::test]
async fn update_text_cell_event_test() { async fn update_text_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -449,7 +449,7 @@ async fn update_text_cell_event_test() {
#[tokio::test] #[tokio::test]
async fn update_checkbox_cell_event_test() { async fn update_checkbox_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -480,7 +480,7 @@ async fn update_checkbox_cell_event_test() {
#[tokio::test] #[tokio::test]
async fn update_single_select_cell_event_test() { async fn update_single_select_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -507,7 +507,7 @@ async fn update_single_select_cell_event_test() {
#[tokio::test] #[tokio::test]
async fn update_date_cell_event_test() { async fn update_date_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -544,7 +544,7 @@ async fn update_date_cell_event_test() {
#[tokio::test] #[tokio::test]
async fn update_date_cell_event_with_empty_time_str_test() { async fn update_date_cell_event_with_empty_time_str_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -580,7 +580,7 @@ async fn update_date_cell_event_with_empty_time_str_test() {
#[tokio::test] #[tokio::test]
async fn create_checklist_field_test() { async fn create_checklist_field_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -601,7 +601,7 @@ async fn create_checklist_field_test() {
#[tokio::test] #[tokio::test]
async fn update_checklist_cell_test() { async fn update_checklist_cell_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -658,7 +658,7 @@ async fn update_checklist_cell_test() {
#[tokio::test] #[tokio::test]
async fn get_groups_event_with_grid_test() { async fn get_groups_event_with_grid_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my board view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -670,7 +670,7 @@ async fn get_groups_event_with_grid_test() {
#[tokio::test] #[tokio::test]
async fn get_groups_event_test() { async fn get_groups_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let board_view = test let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![]) .create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -682,7 +682,7 @@ async fn get_groups_event_test() {
#[tokio::test] #[tokio::test]
async fn move_group_event_test() { async fn move_group_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let board_view = test let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![]) .create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -716,7 +716,7 @@ async fn move_group_event_test() {
#[tokio::test] #[tokio::test]
async fn move_group_event_with_invalid_id_test() { async fn move_group_event_with_invalid_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let board_view = test let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![]) .create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -738,7 +738,7 @@ async fn move_group_event_with_invalid_id_test() {
#[tokio::test] #[tokio::test]
async fn rename_group_event_test() { async fn rename_group_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let board_view = test let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![]) .create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -763,7 +763,7 @@ async fn rename_group_event_test() {
#[tokio::test] #[tokio::test]
async fn hide_group_event_test() { async fn hide_group_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let board_view = test let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![]) .create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -791,7 +791,7 @@ async fn hide_group_event_test() {
#[tokio::test] #[tokio::test]
async fn update_database_layout_event_test() { async fn update_database_layout_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -813,7 +813,7 @@ async fn update_database_layout_event_test() {
#[tokio::test] #[tokio::test]
async fn update_database_layout_event_test2() { async fn update_database_layout_event_test2() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let grid_view = test let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![]) .create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await; .await;
@ -845,7 +845,7 @@ async fn update_database_layout_event_test2() {
#[tokio::test] #[tokio::test]
async fn set_group_by_checkbox_field_test() { async fn set_group_by_checkbox_field_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let board_view = test let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![]) .create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await; .await;
@ -862,7 +862,7 @@ async fn set_group_by_checkbox_field_test() {
#[tokio::test] #[tokio::test]
async fn get_all_calendar_event_test() { async fn get_all_calendar_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let calendar_view = test let calendar_view = test
.create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![]) .create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![])
.await; .await;
@ -875,7 +875,7 @@ async fn get_all_calendar_event_test() {
#[tokio::test] #[tokio::test]
async fn create_calendar_event_test() { async fn create_calendar_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let calendar_view = test let calendar_view = test
.create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![]) .create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![])
.await; .await;

View File

@ -38,11 +38,7 @@ impl FlowySupabaseDatabaseTest {
let current_workspace = self.inner.get_current_workspace().await; let current_workspace = self.inner.get_current_workspace().await;
let view = self let view = self
.inner .inner
.create_grid( .create_grid(&current_workspace.id, "my database".to_string(), vec![])
&current_workspace.workspace.id,
"my database".to_string(),
vec![],
)
.await; .await;
let database = self.inner.get_database(&view.id).await; let database = self.inner.get_database(&view.id).await;
(view, database) (view, database)

View File

@ -18,11 +18,7 @@ impl AFCloudDocumentTest {
let current_workspace = self.inner.get_current_workspace().await; let current_workspace = self.inner.get_current_workspace().await;
let view = self let view = self
.inner .inner
.create_document( .create_document(&current_workspace.id, "my document".to_string(), vec![])
&current_workspace.workspace.id,
"my document".to_string(),
vec![],
)
.await; .await;
view.id view.id
} }

View File

@ -12,7 +12,7 @@ use crate::document::supabase_test::helper::FlowySupabaseDocumentTest;
#[tokio::test] #[tokio::test]
async fn supabase_document_upload_text_file_test() { async fn supabase_document_upload_text_file_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await { if let Some(test) = FlowySupabaseDocumentTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
let storage_service = test let storage_service = test
.document_manager .document_manager
.get_file_storage_service() .get_file_storage_service()
@ -43,7 +43,7 @@ async fn supabase_document_upload_text_file_test() {
#[tokio::test] #[tokio::test]
async fn supabase_document_upload_zip_file_test() { async fn supabase_document_upload_zip_file_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await { if let Some(test) = FlowySupabaseDocumentTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
let storage_service = test let storage_service = test
.document_manager .document_manager
.get_file_storage_service() .get_file_storage_service()
@ -85,7 +85,7 @@ async fn supabase_document_upload_zip_file_test() {
#[tokio::test] #[tokio::test]
async fn supabase_document_upload_image_test() { async fn supabase_document_upload_image_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await { if let Some(test) = FlowySupabaseDocumentTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
let storage_service = test let storage_service = test
.document_manager .document_manager
.get_file_storage_service() .get_file_storage_service()

View File

@ -23,11 +23,7 @@ impl FlowySupabaseDocumentTest {
let current_workspace = self.inner.get_current_workspace().await; let current_workspace = self.inner.get_current_workspace().await;
self self
.inner .inner
.create_document( .create_document(&current_workspace.id, "my document".to_string(), vec![])
&current_workspace.workspace.id,
"my document".to_string(),
vec![],
)
.await .await
} }

View File

@ -1,53 +1,10 @@
use collab_folder::core::ViewLayout; use collab_folder::ViewLayout;
use flowy_folder2::entities::icon::{ViewIconPB, ViewIconTypePB}; use flowy_folder2::entities::icon::{ViewIconPB, ViewIconTypePB};
use crate::folder::local_test::script::FolderScript::*; use crate::folder::local_test::script::FolderScript::*;
use crate::folder::local_test::script::FolderTest; use crate::folder::local_test::script::FolderTest;
#[tokio::test]
async fn read_all_workspace_test() {
let mut test = FolderTest::new().await;
test.run_scripts(vec![ReadAllWorkspaces]).await;
assert!(!test.all_workspace.is_empty());
}
#[tokio::test]
async fn create_workspace_test() {
let mut test = FolderTest::new().await;
let name = "My new workspace".to_owned();
let desc = "Daily routines".to_owned();
test
.run_scripts(vec![CreateWorkspace {
name: name.clone(),
desc: desc.clone(),
}])
.await;
let workspace = test.workspace.clone();
assert_eq!(workspace.name, name);
test
.run_scripts(vec![
ReadWorkspace(Some(workspace.id.clone())),
AssertWorkspace(workspace),
])
.await;
}
#[tokio::test]
async fn get_workspace_test() {
let mut test = FolderTest::new().await;
let workspace = test.workspace.clone();
test
.run_scripts(vec![
ReadWorkspace(Some(workspace.id.clone())),
AssertWorkspace(workspace),
])
.await;
}
#[tokio::test] #[tokio::test]
async fn create_parent_view_test() { async fn create_parent_view_test() {
let mut test = FolderTest::new().await; let mut test = FolderTest::new().await;

View File

@ -1,4 +1,4 @@
use collab_folder::core::ViewLayout; use collab_folder::ViewLayout;
use event_integration::event_builder::EventBuilder; use event_integration::event_builder::EventBuilder;
use event_integration::EventIntegrationTest; use event_integration::EventIntegrationTest;
@ -7,14 +7,15 @@ use flowy_folder2::entities::*;
use flowy_folder2::event_map::FolderEvent::*; use flowy_folder2::event_map::FolderEvent::*;
pub enum FolderScript { pub enum FolderScript {
// Workspace #[allow(dead_code)]
ReadAllWorkspaces,
CreateWorkspace { CreateWorkspace {
name: String, name: String,
desc: String, desc: String,
}, },
#[allow(dead_code)]
AssertWorkspace(WorkspacePB), AssertWorkspace(WorkspacePB),
ReadWorkspace(Option<String>), #[allow(dead_code)]
ReadWorkspace(String),
// App // App
CreateParentView { CreateParentView {
@ -65,7 +66,6 @@ pub enum FolderScript {
pub struct FolderTest { pub struct FolderTest {
pub sdk: EventIntegrationTest, pub sdk: EventIntegrationTest,
pub all_workspace: Vec<WorkspacePB>,
pub workspace: WorkspacePB, pub workspace: WorkspacePB,
pub parent_view: ViewPB, pub parent_view: ViewPB,
pub child_view: ViewPB, pub child_view: ViewPB,
@ -77,8 +77,15 @@ impl FolderTest {
pub async fn new() -> Self { pub async fn new() -> Self {
let sdk = EventIntegrationTest::new().await; let sdk = EventIntegrationTest::new().await;
let _ = sdk.init_anon_user().await; let _ = sdk.init_anon_user().await;
let workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await; let workspace = sdk.folder_manager.get_current_workspace().await.unwrap();
let parent_view = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await; let parent_view = create_view(
&sdk,
&workspace.id,
"Folder App",
"Folder test app",
ViewLayout::Document,
)
.await;
let view = create_view( let view = create_view(
&sdk, &sdk,
&parent_view.id, &parent_view.id,
@ -89,7 +96,6 @@ impl FolderTest {
.await; .await;
Self { Self {
sdk, sdk,
all_workspace: vec![],
workspace, workspace,
parent_view, parent_view,
child_view: view, child_view: view,
@ -107,10 +113,6 @@ impl FolderTest {
pub async fn run_script(&mut self, script: FolderScript) { pub async fn run_script(&mut self, script: FolderScript) {
let sdk = &self.sdk; let sdk = &self.sdk;
match script { match script {
FolderScript::ReadAllWorkspaces => {
let all_workspace = read_workspace(sdk, None).await;
self.all_workspace = all_workspace;
},
FolderScript::CreateWorkspace { name, desc } => { FolderScript::CreateWorkspace { name, desc } => {
let workspace = create_workspace(sdk, &name, &desc).await; let workspace = create_workspace(sdk, &name, &desc).await;
self.workspace = workspace; self.workspace = workspace;
@ -119,11 +121,11 @@ impl FolderTest {
assert_eq!(self.workspace, workspace, "Workspace not equal"); assert_eq!(self.workspace, workspace, "Workspace not equal");
}, },
FolderScript::ReadWorkspace(workspace_id) => { FolderScript::ReadWorkspace(workspace_id) => {
let workspace = read_workspace(sdk, workspace_id).await.pop().unwrap(); let workspace = read_workspace(sdk, workspace_id).await;
self.workspace = workspace; self.workspace = workspace;
}, },
FolderScript::CreateParentView { name, desc } => { FolderScript::CreateParentView { name, desc } => {
let app = create_app(sdk, &self.workspace.id, &name, &desc).await; let app = create_view(sdk, &self.workspace.id, &name, &desc, ViewLayout::Document).await;
self.parent_view = app; self.parent_view = app;
}, },
FolderScript::AssertParentView(app) => { FolderScript::AssertParentView(app) => {
@ -215,70 +217,27 @@ pub async fn create_workspace(sdk: &EventIntegrationTest, name: &str, desc: &str
.parse::<WorkspacePB>() .parse::<WorkspacePB>()
} }
pub async fn read_workspace( pub async fn read_workspace(sdk: &EventIntegrationTest, workspace_id: String) -> WorkspacePB {
sdk: &EventIntegrationTest,
workspace_id: Option<String>,
) -> Vec<WorkspacePB> {
let request = WorkspaceIdPB { let request = WorkspaceIdPB {
value: workspace_id, value: workspace_id,
}; };
let repeated_workspace = EventBuilder::new(sdk.clone()) EventBuilder::new(sdk.clone())
.event(ReadAllWorkspaces) .event(ReadCurrentWorkspace)
.payload(request.clone()) .payload(request.clone())
.async_send() .async_send()
.await .await
.parse::<RepeatedWorkspacePB>(); .parse::<WorkspacePB>()
let workspaces;
if let Some(workspace_id) = &request.value {
workspaces = repeated_workspace
.items
.into_iter()
.filter(|workspace| &workspace.id == workspace_id)
.collect::<Vec<WorkspacePB>>();
debug_assert_eq!(workspaces.len(), 1);
} else {
workspaces = repeated_workspace.items;
}
workspaces
}
pub async fn create_app(
sdk: &EventIntegrationTest,
workspace_id: &str,
name: &str,
desc: &str,
) -> ViewPB {
let create_view_request = CreateViewPayloadPB {
parent_view_id: workspace_id.to_owned(),
name: name.to_string(),
desc: desc.to_string(),
thumbnail: None,
layout: ViewLayout::Document.into(),
initial_data: vec![],
meta: Default::default(),
set_as_current: true,
index: None,
};
EventBuilder::new(sdk.clone())
.event(CreateView)
.payload(create_view_request)
.async_send()
.await
.parse::<ViewPB>()
} }
pub async fn create_view( pub async fn create_view(
sdk: &EventIntegrationTest, sdk: &EventIntegrationTest,
app_id: &str, parent_view_id: &str,
name: &str, name: &str,
desc: &str, desc: &str,
layout: ViewLayout, layout: ViewLayout,
) -> ViewPB { ) -> ViewPB {
let request = CreateViewPayloadPB { let request = CreateViewPayloadPB {
parent_view_id: app_id.to_string(), parent_view_id: parent_view_id.to_string(),
name: name.to_string(), name: name.to_string(),
desc: desc.to_string(), desc: desc.to_string(),
thumbnail: None, thumbnail: None,

View File

@ -17,7 +17,7 @@ use crate::util::receive_with_timeout;
/// 6. Ensure that the received views contain the newly created "test_view". /// 6. Ensure that the received views contain the newly created "test_view".
async fn create_child_view_in_workspace_subscription_test() { async fn create_child_view_in_workspace_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let workspace = test.get_current_workspace().await.workspace; let workspace = test.get_current_workspace().await;
let rx = test let rx = test
.notification_sender .notification_sender
.subscribe::<RepeatedViewPB>(&workspace.id, FolderNotification::DidUpdateWorkspaceViews); .subscribe::<RepeatedViewPB>(&workspace.id, FolderNotification::DidUpdateWorkspaceViews);
@ -41,7 +41,7 @@ async fn create_child_view_in_workspace_subscription_test() {
#[tokio::test] #[tokio::test]
async fn create_child_view_in_view_subscription_test() { async fn create_child_view_in_view_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let mut workspace = test.get_current_workspace().await.workspace; let mut workspace = test.get_current_workspace().await;
let workspace_child_view = workspace.views.pop().unwrap(); let workspace_child_view = workspace.views.pop().unwrap();
let rx = test.notification_sender.subscribe::<ChildViewUpdatePB>( let rx = test.notification_sender.subscribe::<ChildViewUpdatePB>(
&workspace_child_view.id, &workspace_child_view.id,
@ -73,7 +73,7 @@ async fn create_child_view_in_view_subscription_test() {
#[tokio::test] #[tokio::test]
async fn delete_view_subscription_test() { async fn delete_view_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let workspace = test.get_current_workspace().await.workspace; let workspace = test.get_current_workspace().await;
let rx = test let rx = test
.notification_sender .notification_sender
.subscribe::<ChildViewUpdatePB>(&workspace.id, FolderNotification::DidUpdateChildViews); .subscribe::<ChildViewUpdatePB>(&workspace.id, FolderNotification::DidUpdateChildViews);
@ -104,7 +104,7 @@ async fn delete_view_subscription_test() {
#[tokio::test] #[tokio::test]
async fn update_view_subscription_test() { async fn update_view_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let mut workspace = test.get_current_workspace().await.workspace; let mut workspace = test.get_current_workspace().await;
let rx = test let rx = test
.notification_sender .notification_sender
.subscribe::<ChildViewUpdatePB>(&workspace.id, FolderNotification::DidUpdateChildViews); .subscribe::<ChildViewUpdatePB>(&workspace.id, FolderNotification::DidUpdateChildViews);

View File

@ -16,44 +16,45 @@ async fn create_workspace_event_test() {
.payload(request) .payload(request)
.async_send() .async_send()
.await .await
.parse::<flowy_folder2::entities::WorkspacePB>(); .error()
assert_eq!(resp.name, "my second workspace"); .unwrap();
assert_eq!(resp.code, ErrorCode::NotSupportYet);
} }
#[tokio::test] // #[tokio::test]
async fn open_workspace_event_test() { // async fn open_workspace_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; // let test = EventIntegrationTest::new_with_guest_user().await;
let payload = CreateWorkspacePayloadPB { // let payload = CreateWorkspacePayloadPB {
name: "my second workspace".to_owned(), // name: "my second workspace".to_owned(),
desc: "".to_owned(), // desc: "".to_owned(),
}; // };
// create a workspace // // create a workspace
let resp_1 = EventBuilder::new(test.clone()) // let resp_1 = EventBuilder::new(test.clone())
.event(flowy_folder2::event_map::FolderEvent::CreateWorkspace) // .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
.payload(payload) // .payload(payload)
.async_send() // .async_send()
.await // .await
.parse::<flowy_folder2::entities::WorkspacePB>(); // .parse::<flowy_folder2::entities::WorkspacePB>();
//
// open the workspace // // open the workspace
let payload = WorkspaceIdPB { // let payload = WorkspaceIdPB {
value: Some(resp_1.id.clone()), // value: Some(resp_1.id.clone()),
}; // };
let resp_2 = EventBuilder::new(test) // let resp_2 = EventBuilder::new(test)
.event(flowy_folder2::event_map::FolderEvent::OpenWorkspace) // .event(flowy_folder2::event_map::FolderEvent::OpenWorkspace)
.payload(payload) // .payload(payload)
.async_send() // .async_send()
.await // .await
.parse::<flowy_folder2::entities::WorkspacePB>(); // .parse::<flowy_folder2::entities::WorkspacePB>();
//
assert_eq!(resp_1.id, resp_2.id); // assert_eq!(resp_1.id, resp_2.id);
assert_eq!(resp_1.name, resp_2.name); // assert_eq!(resp_1.name, resp_2.name);
} // }
#[tokio::test] #[tokio::test]
async fn create_view_event_test() { async fn create_view_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let view = test let view = test
.create_view(&current_workspace.id, "My first view".to_string()) .create_view(&current_workspace.id, "My first view".to_string())
.await; .await;
@ -65,7 +66,7 @@ async fn create_view_event_test() {
#[tokio::test] #[tokio::test]
async fn update_view_event_with_name_test() { async fn update_view_event_with_name_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let view = test let view = test
.create_view(&current_workspace.id, "My first view".to_string()) .create_view(&current_workspace.id, "My first view".to_string())
.await; .await;
@ -86,7 +87,7 @@ async fn update_view_event_with_name_test() {
#[tokio::test] #[tokio::test]
async fn update_view_icon_event_test() { async fn update_view_icon_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let view = test let view = test
.create_view(&current_workspace.id, "My first view".to_string()) .create_view(&current_workspace.id, "My first view".to_string())
.await; .await;
@ -110,7 +111,7 @@ async fn update_view_icon_event_test() {
#[tokio::test] #[tokio::test]
async fn delete_view_event_test() { async fn delete_view_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let view = test let view = test
.create_view(&current_workspace.id, "My first view".to_string()) .create_view(&current_workspace.id, "My first view".to_string())
.await; .await;
@ -133,7 +134,7 @@ async fn delete_view_event_test() {
#[tokio::test] #[tokio::test]
async fn put_back_trash_event_test() { async fn put_back_trash_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let view = test let view = test
.create_view(&current_workspace.id, "My first view".to_string()) .create_view(&current_workspace.id, "My first view".to_string())
.await; .await;
@ -176,7 +177,7 @@ async fn put_back_trash_event_test() {
#[tokio::test] #[tokio::test]
async fn delete_view_permanently_event_test() { async fn delete_view_permanently_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let view = test let view = test
.create_view(&current_workspace.id, "My first view".to_string()) .create_view(&current_workspace.id, "My first view".to_string())
.await; .await;
@ -225,7 +226,7 @@ async fn delete_view_permanently_event_test() {
#[tokio::test] #[tokio::test]
async fn delete_all_trash_test() { async fn delete_all_trash_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
for i in 0..3 { for i in 0..3 {
let view = test let view = test
@ -269,7 +270,7 @@ async fn delete_all_trash_test() {
#[tokio::test] #[tokio::test]
async fn multiple_hierarchy_view_test() { async fn multiple_hierarchy_view_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
for i in 1..4 { for i in 1..4 {
let parent = test let parent = test
.create_view(&current_workspace.id, format!("My {} view", i)) .create_view(&current_workspace.id, format!("My {} view", i))
@ -345,7 +346,7 @@ async fn multiple_hierarchy_view_test() {
#[tokio::test] #[tokio::test]
async fn move_view_event_test() { async fn move_view_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
for i in 1..4 { for i in 1..4 {
let parent = test let parent = test
.create_view(&current_workspace.id, format!("My {} view", i)) .create_view(&current_workspace.id, format!("My {} view", i))
@ -383,7 +384,7 @@ async fn move_view_event_test() {
#[tokio::test] #[tokio::test]
async fn move_view_event_after_delete_view_test() { async fn move_view_event_after_delete_view_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
for i in 1..6 { for i in 1..6 {
let _ = test let _ = test
.create_view(&current_workspace.id, format!("My {} view", i)) .create_view(&current_workspace.id, format!("My {} view", i))
@ -425,7 +426,7 @@ async fn move_view_event_after_delete_view_test() {
#[tokio::test] #[tokio::test]
async fn move_view_event_after_delete_view_test2() { async fn move_view_event_after_delete_view_test2() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let parent = test let parent = test
.create_view(&current_workspace.id, "My view".to_string()) .create_view(&current_workspace.id, "My view".to_string())
.await; .await;
@ -495,7 +496,7 @@ fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
#[tokio::test] #[tokio::test]
async fn move_view_across_parent_test() { async fn move_view_across_parent_test() {
let test = EventIntegrationTest::new_with_guest_user().await; let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace; let current_workspace = test.get_current_workspace().await;
let parent_1 = test let parent_1 = test
.create_view(&current_workspace.id, "My view 1".to_string()) .create_view(&current_workspace.id, "My view 1".to_string())
.await; .await;

View File

@ -5,7 +5,7 @@ use collab::core::collab::MutexCollab;
use collab::core::origin::CollabOrigin; use collab::core::origin::CollabOrigin;
use collab::preclude::updates::decoder::Decode; use collab::preclude::updates::decoder::Decode;
use collab::preclude::{merge_updates_v1, JsonValue, Update}; use collab::preclude::{merge_updates_v1, JsonValue, Update};
use collab_folder::core::FolderData; use collab_folder::FolderData;
use event_integration::event_builder::EventBuilder; use event_integration::event_builder::EventBuilder;
use flowy_folder2::entities::{FolderSnapshotPB, RepeatedFolderSnapshotPB, WorkspaceIdPB}; use flowy_folder2::entities::{FolderSnapshotPB, RepeatedFolderSnapshotPB, WorkspaceIdPB};
@ -39,7 +39,7 @@ impl FlowySupabaseFolderTest {
EventBuilder::new(self.inner.deref().clone()) EventBuilder::new(self.inner.deref().clone())
.event(GetFolderSnapshots) .event(GetFolderSnapshots)
.payload(WorkspaceIdPB { .payload(WorkspaceIdPB {
value: Some(workspace_id.to_string()), value: workspace_id.to_string(),
}) })
.async_send() .async_send()
.await .await

View File

@ -12,11 +12,12 @@ use crate::util::{get_folder_data_from_server, receive_with_timeout};
#[tokio::test] #[tokio::test]
async fn supabase_encrypt_folder_test() { async fn supabase_encrypt_folder_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await { if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let secret = test.enable_encryption().await; let secret = test.enable_encryption().await;
let local_folder_data = test.get_local_folder_data().await; let local_folder_data = test.get_local_folder_data().await;
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
let remote_folder_data = get_folder_data_from_server(&workspace_id, Some(secret)) let remote_folder_data = get_folder_data_from_server(&uid, &workspace_id, Some(secret))
.await .await
.unwrap() .unwrap()
.unwrap(); .unwrap();
@ -28,8 +29,9 @@ async fn supabase_encrypt_folder_test() {
#[tokio::test] #[tokio::test]
async fn supabase_decrypt_folder_data_test() { async fn supabase_decrypt_folder_data_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await { if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let secret = Some(test.enable_encryption().await); let secret = Some(test.enable_encryption().await);
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
test test
.create_view(&workspace_id, "encrypt view".to_string()) .create_view(&workspace_id, "encrypt view".to_string())
.await; .await;
@ -41,7 +43,7 @@ async fn supabase_decrypt_folder_data_test() {
receive_with_timeout(rx, Duration::from_secs(10)) receive_with_timeout(rx, Duration::from_secs(10))
.await .await
.unwrap(); .unwrap();
let folder_data = get_folder_data_from_server(&workspace_id, secret) let folder_data = get_folder_data_from_server(&uid, &workspace_id, secret)
.await .await
.unwrap() .unwrap()
.unwrap(); .unwrap();
@ -54,8 +56,9 @@ async fn supabase_decrypt_folder_data_test() {
#[should_panic] #[should_panic]
async fn supabase_decrypt_with_invalid_secret_folder_data_test() { async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await { if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let _ = Some(test.enable_encryption().await); let _ = Some(test.enable_encryption().await);
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
test test
.create_view(&workspace_id, "encrypt view".to_string()) .create_view(&workspace_id, "encrypt view".to_string())
.await; .await;
@ -66,7 +69,7 @@ async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
.await .await
.unwrap(); .unwrap();
let _ = get_folder_data_from_server(&workspace_id, Some("invalid secret".to_string())) let _ = get_folder_data_from_server(&uid, &workspace_id, Some("invalid secret".to_string()))
.await .await
.unwrap(); .unwrap();
} }
@ -74,7 +77,7 @@ async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
#[tokio::test] #[tokio::test]
async fn supabase_folder_snapshot_test() { async fn supabase_folder_snapshot_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await { if let Some(test) = FlowySupabaseFolderTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
let rx = test let rx = test
.notification_sender .notification_sender
.subscribe::<FolderSnapshotStatePB>(&workspace_id, DidUpdateFolderSnapshotState); .subscribe::<FolderSnapshotStatePB>(&workspace_id, DidUpdateFolderSnapshotState);
@ -92,7 +95,7 @@ async fn supabase_folder_snapshot_test() {
#[tokio::test] #[tokio::test]
async fn supabase_initial_folder_snapshot_test2() { async fn supabase_initial_folder_snapshot_test2() {
if let Some(test) = FlowySupabaseFolderTest::new().await { if let Some(test) = FlowySupabaseFolderTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id; let workspace_id = test.get_current_workspace().await.id;
test test
.create_view(&workspace_id, "supabase test view1".to_string()) .create_view(&workspace_id, "supabase test view1".to_string())

View File

@ -38,3 +38,25 @@ async fn migrate_020_historical_empty_document_test() {
assert_eq!(database.rows.len(), 3); assert_eq!(database.rows.len(), 3);
drop(cleaner); drop(cleaner);
} }
#[tokio::test]
async fn migrate_036_fav_v1_workspace_array_test() {
// Used to test migration: FavoriteV1AndWorkspaceArrayMigration
let (cleaner, user_db_path) = unzip_history_user_db(
"./tests/user/migration_test/history_user_db",
"036_fav_v1_workspace_array",
)
.unwrap();
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
let views = test.get_all_workspace_views().await;
assert_eq!(views.len(), 2);
assert_eq!(views[0].name, "root page");
assert_eq!(views[1].name, "\u{fe0f} Getting started");
let views = test.get_views(&views[1].id).await;
assert_eq!(views.child_views.len(), 3);
assert!(views.child_views[2].is_favorite);
drop(cleaner);
}

View File

@ -4,7 +4,7 @@ use assert_json_diff::assert_json_eq;
use collab_database::rows::database_row_document_id_from_row_id; use collab_database::rows::database_row_document_id_from_row_id;
use collab_document::blocks::DocumentData; use collab_document::blocks::DocumentData;
use collab_entity::CollabType; use collab_entity::CollabType;
use collab_folder::core::FolderData; use collab_folder::FolderData;
use nanoid::nanoid; use nanoid::nanoid;
use serde_json::json; use serde_json::json;
@ -303,21 +303,12 @@ async fn migrate_anon_data_on_cloud_signup() {
let folder_data: FolderData = test let folder_data: FolderData = test
.folder_manager .folder_manager
.get_cloud_service() .get_cloud_service()
.get_folder_data(&user_profile.workspace_id) .get_folder_data(&user_profile.workspace_id, &user_profile.id)
.await .await
.unwrap() .unwrap()
.unwrap(); .unwrap();
let expected_folder_data = expected_workspace_sync_folder_data(); let expected_folder_data = expected_workspace_sync_folder_data();
if folder_data.workspaces.len() != expected_folder_data.workspaces.len() {
dbg!(&folder_data.workspaces);
}
assert_eq!(
folder_data.workspaces.len(),
expected_folder_data.workspaces.len()
);
assert_eq!(folder_data.views.len(), expected_folder_data.views.len()); assert_eq!(folder_data.views.len(), expected_folder_data.views.len());
// After migration, the ids of the folder_data should be different from the expected_folder_data // After migration, the ids of the folder_data should be different from the expected_folder_data
@ -329,10 +320,7 @@ async fn migrate_anon_data_on_cloud_signup() {
assert_eq!(left_view.name, right_view.name); assert_eq!(left_view.name, right_view.name);
} }
assert_ne!( assert_ne!(folder_data.workspace.id, expected_folder_data.workspace.id);
folder_data.current_workspace_id,
expected_folder_data.current_workspace_id
);
assert_ne!(folder_data.current_view, expected_folder_data.current_view); assert_ne!(folder_data.current_view, expected_folder_data.current_view);
let database_views = folder_data let database_views = folder_data

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use event_integration::{event_builder::EventBuilder, EventIntegrationTest}; use event_integration::{event_builder::EventBuilder, EventIntegrationTest};
use flowy_folder2::entities::WorkspaceSettingPB; use flowy_folder2::entities::WorkspaceSettingPB;
use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspace; use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspaceSetting;
use flowy_server::supabase::define::{USER_EMAIL, USER_UUID}; use flowy_server::supabase::define::{USER_EMAIL, USER_UUID};
use flowy_user::entities::{AuthTypePB, OauthSignInPB, UserProfilePB}; use flowy_user::entities::{AuthTypePB, OauthSignInPB, UserProfilePB};
use flowy_user::event_map::UserEvent::*; use flowy_user::event_map::UserEvent::*;
@ -32,7 +32,7 @@ async fn initial_workspace_test() {
.parse::<UserProfilePB>(); .parse::<UserProfilePB>();
let workspace_settings = EventBuilder::new(test.clone()) let workspace_settings = EventBuilder::new(test.clone())
.event(GetCurrentWorkspace) .event(GetCurrentWorkspaceSetting)
.async_send() .async_send()
.await .await
.parse::<WorkspaceSettingPB>(); .parse::<WorkspaceSettingPB>();

View File

@ -6,7 +6,7 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use anyhow::Error; use anyhow::Error;
use collab_folder::core::FolderData; use collab_folder::FolderData;
use collab_plugins::cloud_storage::RemoteCollabStorage; use collab_plugins::cloud_storage::RemoteCollabStorage;
use nanoid::nanoid; use nanoid::nanoid;
use tokio::sync::mpsc::Receiver; use tokio::sync::mpsc::Receiver;
@ -135,11 +135,12 @@ pub fn encryption_collab_service(
} }
pub async fn get_folder_data_from_server( pub async fn get_folder_data_from_server(
uid: &i64,
folder_id: &str, folder_id: &str,
encryption_secret: Option<String>, encryption_secret: Option<String>,
) -> Result<Option<FolderData>, Error> { ) -> Result<Option<FolderData>, Error> {
let (cloud_service, _encryption) = encryption_folder_service(encryption_secret); let (cloud_service, _encryption) = encryption_folder_service(encryption_secret);
cloud_service.get_folder_data(folder_id).await cloud_service.get_folder_data(folder_id, uid).await
} }
pub async fn get_folder_snapshots( pub async fn get_folder_snapshots(

View File

@ -140,13 +140,18 @@ impl FolderCloudService for ServerProvider {
FutureResult::new(async move { server?.folder_service().create_workspace(uid, &name).await }) FutureResult::new(async move { server?.folder_service().create_workspace(uid, &name).await })
} }
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error> { fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let server = self.get_server(&self.get_server_type()); let server = self.get_server(&self.get_server_type());
let workspace_id = workspace_id.to_string(); let workspace_id = workspace_id.to_string();
FutureResult::new(async move { FutureResult::new(async move {
server? server?
.folder_service() .folder_service()
.get_folder_data(&workspace_id) .get_folder_data(&workspace_id, &uid)
.await .await
}) })
} }

View File

@ -256,6 +256,9 @@ pub enum ErrorCode {
#[error("Internal server error")] #[error("Internal server error")]
InternalServerError = 84, InternalServerError = 84,
#[error("Not support yet")]
NotSupportYet = 85,
} }
impl ErrorCode { impl ErrorCode {

View File

@ -101,6 +101,7 @@ impl FlowyError {
); );
static_flowy_error!(collab_not_sync, ErrorCode::CollabDataNotSync); static_flowy_error!(collab_not_sync, ErrorCode::CollabDataNotSync);
static_flowy_error!(server_error, ErrorCode::InternalServerError); static_flowy_error!(server_error, ErrorCode::InternalServerError);
static_flowy_error!(not_support, ErrorCode::NotSupportYet);
} }
impl std::convert::From<ErrorCode> for FlowyError { impl std::convert::From<ErrorCode> for FlowyError {

View File

@ -1,5 +1,5 @@
pub use anyhow::Error; pub use anyhow::Error;
pub use collab_folder::core::{Folder, FolderData, Workspace}; pub use collab_folder::{Folder, FolderData, Workspace};
use uuid::Uuid; use uuid::Uuid;
use lib_infra::future::FutureResult; use lib_infra::future::FutureResult;
@ -8,7 +8,11 @@ use lib_infra::future::FutureResult;
pub trait FolderCloudService: Send + Sync + 'static { pub trait FolderCloudService: Send + Sync + 'static {
fn create_workspace(&self, uid: i64, name: &str) -> FutureResult<Workspace, Error>; fn create_workspace(&self, uid: i64, name: &str) -> FutureResult<Workspace, Error>;
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error>; fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error>;
fn get_folder_snapshots( fn get_folder_snapshots(
&self, &self,

View File

@ -1,5 +1,5 @@
use crate::entities::parser::view::ViewIdentify; use crate::entities::parser::view::ViewIdentify;
use collab_folder::core::{IconType, ViewIcon}; use collab_folder::{IconType, ViewIcon};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;

View File

@ -1,4 +1,4 @@
use collab_folder::core::TrashInfo; use collab_folder::TrashInfo;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]

View File

@ -3,7 +3,7 @@ use std::convert::TryInto;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::sync::Arc; use std::sync::Arc;
use collab_folder::core::{View, ViewLayout}; use collab_folder::{View, ViewLayout};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;

View File

@ -1,7 +1,7 @@
use std::convert::TryInto; use std::convert::TryInto;
use collab::core::collab_state::SyncState; use collab::core::collab_state::SyncState;
use collab_folder::core::Workspace; use collab_folder::Workspace;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
@ -38,16 +38,16 @@ impl std::convert::From<(Workspace, Vec<ViewPB>)> for WorkspacePB {
} }
} }
impl std::convert::From<Workspace> for WorkspacePB { // impl std::convert::From<Workspace> for WorkspacePB {
fn from(workspace: Workspace) -> Self { // fn from(workspace: Workspace) -> Self {
WorkspacePB { // WorkspacePB {
id: workspace.id, // id: workspace.id,
name: workspace.name, // name: workspace.name,
views: Default::default(), // views: Default::default(),
create_time: workspace.created_at, // create_time: workspace.created_at,
} // }
} // }
} // }
#[derive(PartialEq, Eq, Debug, Default, ProtoBuf)] #[derive(PartialEq, Eq, Debug, Default, ProtoBuf)]
pub struct RepeatedWorkspacePB { pub struct RepeatedWorkspacePB {
@ -55,14 +55,9 @@ pub struct RepeatedWorkspacePB {
pub items: Vec<WorkspacePB>, pub items: Vec<WorkspacePB>,
} }
impl From<Vec<Workspace>> for RepeatedWorkspacePB { impl From<Vec<WorkspacePB>> for RepeatedWorkspacePB {
fn from(workspaces: Vec<Workspace>) -> Self { fn from(workspaces: Vec<WorkspacePB>) -> Self {
Self { Self { items: workspaces }
items: workspaces
.into_iter()
.map(|workspace| workspace.into())
.collect::<Vec<WorkspacePB>>(),
}
} }
} }
@ -98,22 +93,14 @@ impl TryInto<CreateWorkspaceParams> for CreateWorkspacePayloadPB {
// Read all workspaces if the workspace_id is None // Read all workspaces if the workspace_id is None
#[derive(Clone, ProtoBuf, Default, Debug)] #[derive(Clone, ProtoBuf, Default, Debug)]
pub struct WorkspaceIdPB { pub struct WorkspaceIdPB {
#[pb(index = 1, one_of)] #[pb(index = 1)]
pub value: Option<String>, pub value: String,
}
impl WorkspaceIdPB {
pub fn new(workspace_id: Option<String>) -> Self {
Self {
value: workspace_id,
}
}
} }
#[derive(Default, ProtoBuf, Debug, Clone)] #[derive(Default, ProtoBuf, Debug, Clone)]
pub struct WorkspaceSettingPB { pub struct WorkspaceSettingPB {
#[pb(index = 1)] #[pb(index = 1)]
pub workspace: WorkspacePB, pub workspace_id: String,
#[pb(index = 2, one_of)] #[pb(index = 2, one_of)]
pub latest_view: Option<ViewPB>, pub latest_view: Option<ViewPB>,

View File

@ -24,7 +24,18 @@ pub(crate) async fn create_workspace_handler(
let folder = upgrade_folder(folder)?; let folder = upgrade_folder(folder)?;
let params: CreateWorkspaceParams = data.into_inner().try_into()?; let params: CreateWorkspaceParams = data.into_inner().try_into()?;
let workspace = folder.create_workspace(params).await?; let workspace = folder.create_workspace(params).await?;
data_result_ok(workspace.into()) let views = folder
.get_views_belong_to(&workspace.id)
.await?
.into_iter()
.map(view_pb_without_child_views)
.collect::<Vec<ViewPB>>();
data_result_ok(WorkspacePB {
id: workspace.id,
name: workspace.name,
views,
create_time: workspace.created_at,
})
} }
#[tracing::instrument(level = "debug", skip(folder), err)] #[tracing::instrument(level = "debug", skip(folder), err)]
@ -43,52 +54,39 @@ pub(crate) async fn open_workspace_handler(
folder: AFPluginState<Weak<FolderManager>>, folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<WorkspacePB, FlowyError> { ) -> DataResult<WorkspacePB, FlowyError> {
let folder = upgrade_folder(folder)?; let folder = upgrade_folder(folder)?;
let params: WorkspaceIdPB = data.into_inner(); let workspace_id = data.into_inner().value;
match params.value { if workspace_id.is_empty() {
None => Err(FlowyError::workspace_id().with_context("workspace id should not be empty")), Err(FlowyError::workspace_id().with_context("workspace id should not be empty"))
Some(workspace_id) => { } else {
if workspace_id.is_empty() { let workspace = folder.open_workspace(&workspace_id).await?;
Err(FlowyError::workspace_id().with_context("workspace id should not be empty")) let views = folder.get_workspace_views(&workspace_id).await?;
} else { let workspace_pb: WorkspacePB = (workspace, views).into();
let workspace = folder.open_workspace(&workspace_id).await?; data_result_ok(workspace_pb)
let views = folder.get_workspace_views(&workspace_id).await?;
let workspace_pb: WorkspacePB = (workspace, views).into();
data_result_ok(workspace_pb)
}
},
} }
} }
#[tracing::instrument(level = "debug", skip(data, folder), err)]
pub(crate) async fn read_workspaces_handler(
data: AFPluginData<WorkspaceIdPB>,
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<RepeatedWorkspacePB, FlowyError> {
let folder = upgrade_folder(folder)?;
let params: WorkspaceIdPB = data.into_inner();
let workspaces = match params.value {
None => folder.get_all_workspaces().await,
Some(workspace_id) => folder
.get_workspace(&workspace_id)
.await
.map(|workspace| vec![workspace])
.unwrap_or_default(),
};
data_result_ok(workspaces.into())
}
#[tracing::instrument(level = "debug", skip(folder), err)] #[tracing::instrument(level = "debug", skip(folder), err)]
pub async fn get_current_workspace_setting_handler( pub(crate) async fn read_current_workspace_setting_handler(
folder: AFPluginState<Weak<FolderManager>>, folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<WorkspaceSettingPB, FlowyError> { ) -> DataResult<WorkspaceSettingPB, FlowyError> {
let folder = upgrade_folder(folder)?; let folder = upgrade_folder(folder)?;
let workspace = folder.get_current_workspace().await?; let setting = folder
let latest_view: Option<ViewPB> = folder.get_current_view().await; .get_workspace_setting_pb()
data_result_ok(WorkspaceSettingPB { .await
workspace, .ok_or(FlowyError::record_not_found())?;
latest_view, data_result_ok(setting)
}) }
#[tracing::instrument(level = "debug", skip(folder), err)]
pub(crate) async fn read_current_workspace_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<WorkspacePB, FlowyError> {
let folder = upgrade_folder(folder)?;
let workspace = folder
.get_workspace_pb()
.await
.ok_or(FlowyError::record_not_found())?;
data_result_ok(workspace)
} }
pub(crate) async fn create_view_handler( pub(crate) async fn create_view_handler(
@ -125,7 +123,7 @@ pub(crate) async fn read_view_handler(
) -> DataResult<ViewPB, FlowyError> { ) -> DataResult<ViewPB, FlowyError> {
let folder = upgrade_folder(folder)?; let folder = upgrade_folder(folder)?;
let view_id: ViewIdPB = data.into_inner(); let view_id: ViewIdPB = data.into_inner();
let view_pb = folder.get_view(&view_id.value).await?; let view_pb = folder.get_view_pb(&view_id.value).await?;
data_result_ok(view_pb) data_result_ok(view_pb)
} }
@ -239,17 +237,10 @@ pub(crate) async fn read_favorites_handler(
let favorites = folder.get_all_favorites().await; let favorites = folder.get_all_favorites().await;
let mut views = vec![]; let mut views = vec![];
for info in favorites { for info in favorites {
let view = folder.get_view(&info.id).await; if let Ok(view) = folder.get_view_pb(&info.id).await {
match view { views.push(view);
Ok(view) => {
views.push(view);
},
Err(err) => {
return Err(err);
},
} }
} }
data_result_ok(RepeatedViewPB { items: views }) data_result_ok(RepeatedViewPB { items: views })
} }
#[tracing::instrument(level = "debug", skip(folder), err)] #[tracing::instrument(level = "debug", skip(folder), err)]
@ -319,10 +310,7 @@ pub(crate) async fn get_folder_snapshots_handler(
folder: AFPluginState<Weak<FolderManager>>, folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<RepeatedFolderSnapshotPB, FlowyError> { ) -> DataResult<RepeatedFolderSnapshotPB, FlowyError> {
let folder = upgrade_folder(folder)?; let folder = upgrade_folder(folder)?;
if let Some(workspace_id) = &data.value { let data = data.into_inner();
let snapshots = folder.get_folder_snapshots(workspace_id, 10).await?; let snapshots = folder.get_folder_snapshots(&data.value, 10).await?;
data_result_ok(RepeatedFolderSnapshotPB { items: snapshots }) data_result_ok(RepeatedFolderSnapshotPB { items: snapshots })
} else {
data_result_ok(RepeatedFolderSnapshotPB { items: vec![] })
}
} }

View File

@ -12,11 +12,8 @@ pub fn init(folder: Weak<FolderManager>) -> AFPlugin {
AFPlugin::new().name("Flowy-Folder").state(folder) AFPlugin::new().name("Flowy-Folder").state(folder)
// Workspace // Workspace
.event(FolderEvent::CreateWorkspace, create_workspace_handler) .event(FolderEvent::CreateWorkspace, create_workspace_handler)
.event( .event(FolderEvent::GetCurrentWorkspaceSetting, read_current_workspace_setting_handler)
FolderEvent::GetCurrentWorkspace, .event(FolderEvent::ReadCurrentWorkspace, read_current_workspace_handler)
get_current_workspace_setting_handler,
)
.event(FolderEvent::ReadAllWorkspaces, read_workspaces_handler)
.event(FolderEvent::OpenWorkspace, open_workspace_handler) .event(FolderEvent::OpenWorkspace, open_workspace_handler)
.event(FolderEvent::ReadWorkspaceViews, get_workspace_views_handler) .event(FolderEvent::ReadWorkspaceViews, get_workspace_views_handler)
// View // View
@ -52,11 +49,11 @@ pub enum FolderEvent {
/// Read the current opening workspace. Currently, we only support one workspace /// Read the current opening workspace. Currently, we only support one workspace
#[event(output = "WorkspaceSettingPB")] #[event(output = "WorkspaceSettingPB")]
GetCurrentWorkspace = 1, GetCurrentWorkspaceSetting = 1,
/// Return a list of workspaces that the current user can access. /// Return a list of workspaces that the current user can access.
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")] #[event(output = "WorkspacePB")]
ReadAllWorkspaces = 2, ReadCurrentWorkspace = 2,
/// Delete the workspace /// Delete the workspace
#[event(input = "WorkspaceIdPB")] #[event(input = "WorkspaceIdPB")]

View File

@ -1,4 +1,4 @@
pub use collab_folder::core::ViewLayout; pub use collab_folder::ViewLayout;
pub mod entities; pub mod entities;
pub mod event_handler; pub mod event_handler;

View File

@ -5,9 +5,9 @@ use std::sync::{Arc, Weak};
use collab::core::collab::{CollabRawData, MutexCollab}; use collab::core::collab::{CollabRawData, MutexCollab};
use collab::core::collab_state::SyncState; use collab::core::collab_state::SyncState;
use collab_entity::CollabType; use collab_entity::CollabType;
use collab_folder::core::{ use collab_folder::{
FavoritesInfo, Folder, FolderData, FolderNotify, TrashChange, TrashChangeReceiver, TrashInfo, FavoriteId, Folder, FolderData, FolderNotify, TrashChange, TrashChangeReceiver, TrashInfo,
View, ViewChange, ViewChangeReceiver, ViewLayout, ViewUpdate, Workspace, UserId, View, ViewChange, ViewChangeReceiver, ViewLayout, ViewUpdate, Workspace,
}; };
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use tokio_stream::wrappers::WatchStream; use tokio_stream::wrappers::WatchStream;
@ -24,12 +24,11 @@ use crate::entities::icon::UpdateViewIconParams;
use crate::entities::{ use crate::entities::{
view_pb_with_child_views, view_pb_without_child_views, ChildViewUpdatePB, CreateViewParams, view_pb_with_child_views, view_pb_without_child_views, ChildViewUpdatePB, CreateViewParams,
CreateWorkspaceParams, DeletedViewPB, FolderSnapshotPB, FolderSnapshotStatePB, FolderSyncStatePB, CreateWorkspaceParams, DeletedViewPB, FolderSnapshotPB, FolderSnapshotStatePB, FolderSyncStatePB,
RepeatedTrashPB, RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, UserFolderPB, ViewPB, RepeatedTrashPB, RepeatedViewPB, UpdateViewParams, UserFolderPB, ViewPB, WorkspacePB,
WorkspacePB, WorkspaceSettingPB,
}; };
use crate::notification::{ use crate::notification::{
send_notification, send_workspace_notification, send_workspace_setting_notification, send_notification, send_workspace_setting_notification, FolderNotification,
FolderNotification,
}; };
use crate::share::ImportParams; use crate::share::ImportParams;
use crate::user_default::DefaultFolderBuilder; use crate::user_default::DefaultFolderBuilder;
@ -74,6 +73,7 @@ impl FolderManager {
Ok(manager) Ok(manager)
} }
#[instrument(level = "debug", skip(self), err)]
pub async fn get_current_workspace(&self) -> FlowyResult<WorkspacePB> { pub async fn get_current_workspace(&self) -> FlowyResult<WorkspacePB> {
self.with_folder( self.with_folder(
|| { || {
@ -92,19 +92,7 @@ impl FolderManager {
}; };
match folder.get_current_workspace() { match folder.get_current_workspace() {
None => { None => Err(FlowyError::record_not_found().with_context("Can not find the workspace")),
// The current workspace should always exist. If not, try to find the first workspace.
// from the folder. Otherwise, return an error.
let mut workspaces = folder.workspaces.get_all_workspaces();
if workspaces.is_empty() {
Err(FlowyError::record_not_found().with_context("Can not find the workspace"))
} else {
tracing::error!("Can't find the current workspace, use the first workspace");
let workspace = workspaces.remove(0);
folder.set_current_workspace(&workspace.id);
workspace_pb_from_workspace(workspace, folder)
}
},
Some(workspace) => workspace_pb_from_workspace(workspace, folder), Some(workspace) => workspace_pb_from_workspace(workspace, folder),
} }
}, },
@ -118,9 +106,9 @@ impl FolderManager {
.mutex_folder .mutex_folder
.lock() .lock()
.as_ref() .as_ref()
.map(|folder| folder.get_current_workspace_id()); .map(|folder| folder.get_workspace_id());
if let Some(Some(workspace_id)) = workspace_id { if let Some(workspace_id) = workspace_id {
self.get_workspace_views(&workspace_id).await self.get_workspace_views(&workspace_id).await
} else { } else {
tracing::warn!("Can't get current workspace views"); tracing::warn!("Can't get current workspace views");
@ -129,7 +117,7 @@ impl FolderManager {
} }
pub async fn get_workspace_views(&self, workspace_id: &str) -> FlowyResult<Vec<ViewPB>> { pub async fn get_workspace_views(&self, workspace_id: &str) -> FlowyResult<Vec<ViewPB>> {
let views = self.with_folder(std::vec::Vec::new, |folder| { let views = self.with_folder(Vec::new, |folder| {
get_workspace_view_pbs(workspace_id, folder) get_workspace_view_pbs(workspace_id, folder)
}); });
@ -160,18 +148,25 @@ impl FolderManager {
} => { } => {
let is_exist = is_exist_in_local_disk(&self.user, &workspace_id).unwrap_or(false); let is_exist = is_exist_in_local_disk(&self.user, &workspace_id).unwrap_or(false);
if is_exist { if is_exist {
event!(Level::INFO, "Restore folder from local disk");
let collab = self let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![]) .collab_for_folder(uid, &workspace_id, collab_db, vec![])
.await?; .await?;
Folder::open(collab, Some(folder_notifier)) Folder::open(UserId::from(uid), collab, Some(folder_notifier))?
} else if create_if_not_exist { } else if create_if_not_exist {
event!(Level::INFO, "Create folder with default folder builder");
let folder_data = let folder_data =
DefaultFolderBuilder::build(uid, workspace_id.to_string(), &self.operation_handlers) DefaultFolderBuilder::build(uid, workspace_id.to_string(), &self.operation_handlers)
.await; .await;
let collab = self let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![]) .collab_for_folder(uid, &workspace_id, collab_db, vec![])
.await?; .await?;
Folder::create(collab, Some(folder_notifier), Some(folder_data)) Folder::create(
UserId::from(uid),
collab,
Some(folder_notifier),
folder_data,
)
} else { } else {
return Err(FlowyError::new( return Err(FlowyError::new(
ErrorCode::RecordNotFound, ErrorCode::RecordNotFound,
@ -180,19 +175,26 @@ impl FolderManager {
} }
}, },
FolderInitializeDataSource::Cloud(raw_data) => { FolderInitializeDataSource::Cloud(raw_data) => {
event!(Level::INFO, "Restore folder from cloud service");
if raw_data.is_empty() { if raw_data.is_empty() {
return Err(workspace_data_not_sync_error(uid, &workspace_id)); return Err(workspace_data_not_sync_error(uid, &workspace_id));
} }
let collab = self let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, raw_data) .collab_for_folder(uid, &workspace_id, collab_db, raw_data)
.await?; .await?;
Folder::open(collab, Some(folder_notifier)) Folder::open(UserId::from(uid), collab, Some(folder_notifier))?
}, },
FolderInitializeDataSource::FolderData(folder_data) => { FolderInitializeDataSource::FolderData(folder_data) => {
event!(Level::INFO, "Restore folder with passed-in folder data");
let collab = self let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![]) .collab_for_folder(uid, &workspace_id, collab_db, vec![])
.await?; .await?;
Folder::create(collab, Some(folder_notifier), Some(folder_data)) Folder::create(
UserId::from(uid),
collab,
Some(folder_notifier),
folder_data,
)
}, },
}; };
@ -325,49 +327,58 @@ impl FolderManager {
pub async fn clear(&self, _user_id: i64) {} pub async fn clear(&self, _user_id: i64) {}
#[tracing::instrument(level = "info", skip_all, err)] #[tracing::instrument(level = "info", skip_all, err)]
pub async fn create_workspace(&self, params: CreateWorkspaceParams) -> FlowyResult<Workspace> { pub async fn create_workspace(&self, _params: CreateWorkspaceParams) -> FlowyResult<Workspace> {
let workspace = self Err(FlowyError::not_support())
.cloud_service
.create_workspace(self.user.user_id()?, &params.name)
.await?;
self.with_folder(
|| (),
|folder| {
folder.workspaces.create_workspace(workspace.clone());
folder.set_current_workspace(&workspace.id);
},
);
let repeated_workspace = RepeatedWorkspacePB {
items: vec![workspace.clone().into()],
};
send_workspace_notification(FolderNotification::DidCreateWorkspace, repeated_workspace);
Ok(workspace)
} }
#[tracing::instrument(level = "info", skip_all, err)] #[tracing::instrument(level = "info", skip_all, err)]
pub async fn open_workspace(&self, workspace_id: &str) -> FlowyResult<Workspace> { pub async fn open_workspace(&self, _workspace_id: &str) -> FlowyResult<Workspace> {
self.with_folder( self.with_folder(
|| Err(FlowyError::internal()), || Err(FlowyError::internal()),
|folder| { |folder| {
let workspace = folder let workspace = folder.get_current_workspace().ok_or_else(|| {
.workspaces FlowyError::record_not_found().with_context("Can't open not existing workspace")
.get_workspace(workspace_id) })?;
.ok_or_else(|| {
FlowyError::record_not_found().with_context("Can't open not existing workspace")
})?;
folder.set_current_workspace(&workspace.id);
Ok::<Workspace, FlowyError>(workspace) Ok::<Workspace, FlowyError>(workspace)
}, },
) )
} }
pub async fn get_workspace(&self, workspace_id: &str) -> Option<Workspace> { pub async fn get_workspace(&self, _workspace_id: &str) -> Option<Workspace> {
self.with_folder( self.with_folder(|| None, |folder| folder.get_current_workspace())
|| None, }
|folder| folder.workspaces.get_workspace(workspace_id),
) pub async fn get_workspace_setting_pb(&self) -> Option<WorkspaceSettingPB> {
let workspace_id = self.get_current_workspace_id().await.ok()?;
let latest_view = self.get_current_view().await;
Some(WorkspaceSettingPB {
workspace_id,
latest_view,
})
}
pub async fn get_workspace_pb(&self) -> Option<WorkspacePB> {
let workspace_pb = {
let guard = self.mutex_folder.lock();
let folder = guard.as_ref()?;
let workspace = folder.get_current_workspace()?;
let views = folder
.views
.get_views_belong_to(&workspace.id)
.into_iter()
.map(view_pb_without_child_views)
.collect::<Vec<ViewPB>>();
WorkspacePB {
id: workspace.id,
name: workspace.name,
views,
create_time: workspace.created_at,
}
};
Some(workspace_pb)
} }
async fn get_current_workspace_id(&self) -> FlowyResult<String> { async fn get_current_workspace_id(&self) -> FlowyResult<String> {
@ -375,7 +386,7 @@ impl FolderManager {
.mutex_folder .mutex_folder
.lock() .lock()
.as_ref() .as_ref()
.and_then(|folder| folder.get_current_workspace_id()) .map(|folder| folder.get_workspace_id())
.ok_or(FlowyError::internal().with_context("Unexpected empty workspace id")) .ok_or(FlowyError::internal().with_context("Unexpected empty workspace id"))
} }
@ -399,8 +410,12 @@ impl FolderManager {
} }
pub async fn get_all_workspaces(&self) -> Vec<Workspace> { pub async fn get_all_workspaces(&self) -> Vec<Workspace> {
self.with_folder(std::vec::Vec::new, |folder| { self.with_folder(Vec::new, |folder| {
folder.workspaces.get_all_workspaces() let mut workspaces = vec![];
if let Some(workspace) = folder.get_current_workspace() {
workspaces.push(workspace);
}
workspaces
}) })
} }
@ -478,7 +493,7 @@ impl FolderManager {
/// The child views of the view will only access the first. So if you want to get the child view's /// The child views of the view will only access the first. So if you want to get the child view's
/// child view, you need to call this method again. /// child view, you need to call this method again.
#[tracing::instrument(level = "debug", skip(self, view_id), err)] #[tracing::instrument(level = "debug", skip(self, view_id), err)]
pub async fn get_view(&self, view_id: &str) -> FlowyResult<ViewPB> { pub async fn get_view_pb(&self, view_id: &str) -> FlowyResult<ViewPB> {
let view_id = view_id.to_string(); let view_id = view_id.to_string();
let folder = self.mutex_folder.lock(); let folder = self.mutex_folder.lock();
let folder = folder.as_ref().ok_or_else(folder_not_init_error)?; let folder = folder.as_ref().ok_or_else(folder_not_init_error)?;
@ -586,7 +601,7 @@ impl FolderManager {
new_parent_id: String, new_parent_id: String,
prev_view_id: Option<String>, prev_view_id: Option<String>,
) -> FlowyResult<()> { ) -> FlowyResult<()> {
let view = self.get_view(&view_id).await?; let view = self.get_view_pb(&view_id).await?;
let old_parent_id = view.parent_view_id; let old_parent_id = view.parent_view_id;
self.with_folder( self.with_folder(
|| (), || (),
@ -620,7 +635,7 @@ impl FolderManager {
.collect::<Vec<_>>() .collect::<Vec<_>>()
} else { } else {
self self
.get_view(&parent_view_id) .get_view_pb(&parent_view_id)
.await? .await?
.child_views .child_views
.into_iter() .into_iter()
@ -653,7 +668,7 @@ impl FolderManager {
/// Return a list of views that belong to the given parent view id. /// Return a list of views that belong to the given parent view id.
#[tracing::instrument(level = "debug", skip(self, parent_view_id), err)] #[tracing::instrument(level = "debug", skip(self, parent_view_id), err)]
pub async fn get_views_belong_to(&self, parent_view_id: &str) -> FlowyResult<Vec<Arc<View>>> { pub async fn get_views_belong_to(&self, parent_view_id: &str) -> FlowyResult<Vec<Arc<View>>> {
let views = self.with_folder(std::vec::Vec::new, |folder| { let views = self.with_folder(Vec::new, |folder| {
folder.views.get_views_belong_to(parent_view_id) folder.views.get_views_belong_to(parent_view_id)
}); });
Ok(views) Ok(views)
@ -722,22 +737,22 @@ impl FolderManager {
#[tracing::instrument(level = "trace", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
pub(crate) async fn set_current_view(&self, view_id: &str) -> Result<(), FlowyError> { pub(crate) async fn set_current_view(&self, view_id: &str) -> Result<(), FlowyError> {
let folder = self.mutex_folder.lock(); let workspace_id = self.with_folder(
let folder = folder.as_ref().ok_or_else(folder_not_init_error)?; || Err(FlowyError::record_not_found()),
folder.set_current_view(view_id); |folder| {
folder.set_current_view(view_id);
Ok(folder.get_workspace_id())
},
)?;
let workspace = folder.get_current_workspace(); send_workspace_setting_notification(workspace_id, self.get_current_view().await);
let view = folder
.get_current_view()
.and_then(|view_id| folder.views.get_view(&view_id));
send_workspace_setting_notification(workspace, view);
Ok(()) Ok(())
} }
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn get_current_view(&self) -> Option<ViewPB> { pub(crate) async fn get_current_view(&self) -> Option<ViewPB> {
let view_id = self.with_folder(|| None, |folder| folder.get_current_view())?; let view_id = self.with_folder(|| None, |folder| folder.get_current_view())?;
self.get_view(&view_id).await.ok() self.get_view_pb(&view_id).await.ok()
} }
/// Toggles the favorite status of a view identified by `view_id`If the view is not a favorite, it will be added to the favorites list; otherwise, it will be removed from the list. /// Toggles the favorite status of a view identified by `view_id`If the view is not a favorite, it will be added to the favorites list; otherwise, it will be removed from the list.
@ -761,7 +776,7 @@ impl FolderManager {
// Used by toggle_favorites to send notification to frontend, after the favorite status of view has been changed.It sends two distinct notifications: one to correctly update the concerned view's is_favorite status, and another to update the list of favorites that is to be displayed. // Used by toggle_favorites to send notification to frontend, after the favorite status of view has been changed.It sends two distinct notifications: one to correctly update the concerned view's is_favorite status, and another to update the list of favorites that is to be displayed.
async fn send_toggle_favorite_notification(&self, view_id: &str) { async fn send_toggle_favorite_notification(&self, view_id: &str) {
if let Ok(view) = self.get_view(view_id).await { if let Ok(view) = self.get_view_pb(view_id).await {
let notification_type = if view.is_favorite { let notification_type = if view.is_favorite {
FolderNotification::DidFavoriteView FolderNotification::DidFavoriteView
} else { } else {
@ -780,8 +795,8 @@ impl FolderManager {
} }
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn get_all_favorites(&self) -> Vec<FavoritesInfo> { pub(crate) async fn get_all_favorites(&self) -> Vec<FavoriteId> {
self.with_folder(std::vec::Vec::new, |folder| { self.with_folder(Vec::new, |folder| {
let trash_ids = folder let trash_ids = folder
.get_all_trash() .get_all_trash()
.into_iter() .into_iter()
@ -796,7 +811,7 @@ impl FolderManager {
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn get_all_trash(&self) -> Vec<TrashInfo> { pub(crate) async fn get_all_trash(&self) -> Vec<TrashInfo> {
self.with_folder(std::vec::Vec::new, |folder| folder.get_all_trash()) self.with_folder(Vec::new, |folder| folder.get_all_trash())
} }
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
@ -825,7 +840,7 @@ impl FolderManager {
/// Delete all the trash permanently. /// Delete all the trash permanently.
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn delete_all_trash(&self) { pub(crate) async fn delete_all_trash(&self) {
let deleted_trash = self.with_folder(std::vec::Vec::new, |folder| folder.get_all_trash()); let deleted_trash = self.with_folder(Vec::new, |folder| folder.get_all_trash());
for trash in deleted_trash { for trash in deleted_trash {
let _ = self.delete_trash(&trash.id).await; let _ = self.delete_trash(&trash.id).await;
} }
@ -928,7 +943,7 @@ impl FolderManager {
} }
} }
if let Ok(view_pb) = self.get_view(view_id).await { if let Ok(view_pb) = self.get_view_pb(view_id).await {
send_notification(&view_pb.id, FolderNotification::DidUpdateView) send_notification(&view_pb.id, FolderNotification::DidUpdateView)
.payload(view_pb) .payload(view_pb)
.send(); .send();
@ -1179,7 +1194,7 @@ fn notify_parent_view_did_change<T: AsRef<str>>(
) -> Option<()> { ) -> Option<()> {
let folder = folder.lock(); let folder = folder.lock();
let folder = folder.as_ref()?; let folder = folder.as_ref()?;
let workspace_id = folder.get_current_workspace_id()?; let workspace_id = folder.get_workspace_id();
let trash_ids = folder let trash_ids = folder
.get_all_trash() .get_all_trash()
.into_iter() .into_iter()

View File

@ -1,12 +1,8 @@
use std::sync::Arc;
use collab_folder::core::{View, Workspace};
use flowy_derive::ProtoBuf_Enum; use flowy_derive::ProtoBuf_Enum;
use flowy_notification::NotificationBuilder; use flowy_notification::NotificationBuilder;
use lib_dispatch::prelude::ToBytes; use lib_dispatch::prelude::ToBytes;
use crate::entities::{view_pb_without_child_views, WorkspacePB, WorkspaceSettingPB}; use crate::entities::{ViewPB, WorkspaceSettingPB};
const FOLDER_OBSERVABLE_SOURCE: &str = "Workspace"; const FOLDER_OBSERVABLE_SOURCE: &str = "Workspace";
@ -82,13 +78,11 @@ pub(crate) fn send_workspace_notification<T: ToBytes>(ty: FolderNotification, pa
} }
pub(crate) fn send_workspace_setting_notification( pub(crate) fn send_workspace_setting_notification(
current_workspace: Option<Workspace>, workspace_id: String,
current_view: Option<Arc<View>>, latest_view: Option<ViewPB>,
) -> Option<()> { ) -> Option<()> {
let workspace: WorkspacePB = current_workspace?.into();
let latest_view = current_view.map(view_pb_without_child_views);
let setting = WorkspaceSettingPB { let setting = WorkspaceSettingPB {
workspace, workspace_id,
latest_view, latest_view,
}; };
send_workspace_notification(FolderNotification::DidUpdateWorkspaceSetting, setting); send_workspace_notification(FolderNotification::DidUpdateWorkspaceSetting, setting);

View File

@ -1,4 +1,4 @@
use collab_folder::core::ViewLayout; use collab_folder::ViewLayout;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ImportType { pub enum ImportType {

View File

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use collab_folder::core::{FolderData, RepeatedViewIdentifier, ViewIdentifier, Workspace}; use collab_folder::{FolderData, RepeatedViewIdentifier, ViewIdentifier, Workspace};
use tokio::sync::RwLock; use tokio::sync::RwLock;
use lib_infra::util::timestamp; use lib_infra::util::timestamp;
@ -44,10 +44,10 @@ impl DefaultFolderBuilder {
}; };
FolderData { FolderData {
current_workspace_id: workspace.id.clone(), workspace,
current_view: first_view.id, current_view: first_view.id,
workspaces: vec![workspace],
views: FlattedViews::flatten_views(views), views: FlattedViews::flatten_views(views),
favorites: Default::default(),
} }
} }
} }

View File

@ -3,8 +3,8 @@ use std::future::Future;
use std::sync::Arc; use std::sync::Arc;
use bytes::Bytes; use bytes::Bytes;
pub use collab_folder::core::View; pub use collab_folder::View;
use collab_folder::core::{RepeatedViewIdentifier, ViewIcon, ViewIdentifier, ViewLayout}; use collab_folder::{RepeatedViewIdentifier, ViewIcon, ViewIdentifier, ViewLayout};
use tokio::sync::RwLock; use tokio::sync::RwLock;
use flowy_error::FlowyError; use flowy_error::FlowyError;

View File

@ -1,4 +1,4 @@
use anyhow::Error; use anyhow::{anyhow, Error};
use client_api::entity::QueryCollabParams; use client_api::entity::QueryCollabParams;
use collab::core::origin::CollabOrigin; use collab::core::origin::CollabOrigin;
use collab_entity::CollabType; use collab_entity::CollabType;
@ -16,10 +16,15 @@ where
T: AFServer, T: AFServer,
{ {
fn create_workspace(&self, _uid: i64, _name: &str) -> FutureResult<Workspace, Error> { fn create_workspace(&self, _uid: i64, _name: &str) -> FutureResult<Workspace, Error> {
FutureResult::new(async move { todo!() }) FutureResult::new(async move { Err(anyhow!("Not support yet")) })
} }
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error> { fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let workspace_id = workspace_id.to_string(); let workspace_id = workspace_id.to_string();
let try_get_client = self.0.try_get_client(); let try_get_client = self.0.try_get_client();
FutureResult::new(async move { FutureResult::new(async move {
@ -33,7 +38,7 @@ where
.await .await
.map_err(FlowyError::from)?]; .map_err(FlowyError::from)?];
let folder = let folder =
Folder::from_collab_raw_data(CollabOrigin::Empty, updates, &workspace_id, vec![])?; Folder::from_collab_raw_data(uid, CollabOrigin::Empty, updates, &workspace_id, vec![])?;
Ok(folder.get_folder_data()) Ok(folder.get_folder_data())
}) })
} }

View File

@ -27,7 +27,11 @@ impl FolderCloudService for LocalServerFolderCloudServiceImpl {
}) })
} }
fn get_folder_data(&self, _workspace_id: &str) -> FutureResult<Option<FolderData>, Error> { fn get_folder_data(
&self,
_workspace_id: &str,
_uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
FutureResult::new(async move { Ok(None) }) FutureResult::new(async move { Ok(None) })
} }

View File

@ -69,7 +69,12 @@ where
}) })
} }
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error> { fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let try_get_postgrest = self.server.try_get_postgrest(); let try_get_postgrest = self.server.try_get_postgrest();
let workspace_id = workspace_id.to_string(); let workspace_id = workspace_id.to_string();
FutureResult::new(async move { FutureResult::new(async move {
@ -85,7 +90,7 @@ where
} }
let folder = let folder =
Folder::from_collab_raw_data(CollabOrigin::Empty, updates, &workspace_id, vec![])?; Folder::from_collab_raw_data(uid, CollabOrigin::Empty, updates, &workspace_id, vec![])?;
Ok(folder.get_folder_data()) Ok(folder.get_folder_data())
}) })
} }

View File

@ -17,14 +17,13 @@ use tokio_retry::{Action, RetryIf};
use uuid::Uuid; use uuid::Uuid;
use flowy_error::FlowyError; use flowy_error::FlowyError;
use flowy_folder_deps::cloud::{Folder, Workspace}; use flowy_folder_deps::cloud::{Folder, FolderData, Workspace};
use flowy_user_deps::cloud::*; use flowy_user_deps::cloud::*;
use flowy_user_deps::entities::*; use flowy_user_deps::entities::*;
use flowy_user_deps::DEFAULT_USER_NAME; use flowy_user_deps::DEFAULT_USER_NAME;
use lib_dispatch::prelude::af_spawn; use lib_dispatch::prelude::af_spawn;
use lib_infra::box_any::BoxAny; use lib_infra::box_any::BoxAny;
use lib_infra::future::FutureResult; use lib_infra::future::FutureResult;
use lib_infra::util::timestamp;
use crate::response::ExtendedResponse; use crate::response::ExtendedResponse;
use crate::supabase::api::request::{ use crate::supabase::api::request::{
@ -609,15 +608,9 @@ fn empty_workspace_update(collab_object: &CollabObject) -> Vec<u8> {
&collab_object.object_id, &collab_object.object_id,
vec![], vec![],
)); ));
let folder = Folder::create(collab.clone(), None, None); let workspace = Workspace::new(workspace_id, "My workspace".to_string());
folder.workspaces.create_workspace(Workspace { let folder = Folder::create(collab_object.uid, collab, None, FolderData::new(workspace));
id: workspace_id.clone(), folder.encode_as_update_v1().0
name: "My workspace".to_string(),
child_views: Default::default(),
created_at: timestamp(),
});
folder.set_current_workspace(&workspace_id);
collab.encode_as_update_v1().0
} }
fn oauth_params_from_box_any(any: BoxAny) -> Result<SupabaseOAuthParams, Error> { fn oauth_params_from_box_any(any: BoxAny) -> Result<SupabaseOAuthParams, Error> {

View File

@ -96,15 +96,23 @@ pub fn encryption_collab_service(
} }
#[allow(dead_code)] #[allow(dead_code)]
pub async fn print_encryption_folder(folder_id: &str, encryption_secret: Option<String>) { pub async fn print_encryption_folder(
uid: &i64,
folder_id: &str,
encryption_secret: Option<String>,
) {
let (cloud_service, _encryption) = encryption_folder_service(encryption_secret); let (cloud_service, _encryption) = encryption_folder_service(encryption_secret);
let folder_data = cloud_service.get_folder_data(folder_id).await.unwrap(); let folder_data = cloud_service.get_folder_data(folder_id, uid).await.unwrap();
let json = serde_json::to_value(folder_data).unwrap(); let json = serde_json::to_value(folder_data).unwrap();
println!("{}", serde_json::to_string_pretty(&json).unwrap()); println!("{}", serde_json::to_string_pretty(&json).unwrap());
} }
#[allow(dead_code)] #[allow(dead_code)]
pub async fn print_encryption_folder_snapshot(folder_id: &str, encryption_secret: Option<String>) { pub async fn print_encryption_folder_snapshot(
uid: &i64,
folder_id: &str,
encryption_secret: Option<String>,
) {
let (cloud_service, _encryption) = encryption_collab_service(encryption_secret); let (cloud_service, _encryption) = encryption_collab_service(encryption_secret);
let snapshot = cloud_service let snapshot = cloud_service
.get_snapshots(folder_id, 1) .get_snapshots(folder_id, 1)
@ -115,7 +123,10 @@ pub async fn print_encryption_folder_snapshot(folder_id: &str, encryption_secret
MutexCollab::new_with_raw_data(CollabOrigin::Empty, folder_id, vec![snapshot.blob], vec![]) MutexCollab::new_with_raw_data(CollabOrigin::Empty, folder_id, vec![snapshot.blob], vec![])
.unwrap(), .unwrap(),
); );
let folder_data = Folder::open(collab, None).get_folder_data().unwrap(); let folder_data = Folder::open(uid, collab, None)
.unwrap()
.get_folder_data()
.unwrap();
let json = serde_json::to_value(folder_data).unwrap(); let json = serde_json::to_value(folder_data).unwrap();
println!("{}", serde_json::to_string_pretty(&json).unwrap()); println!("{}", serde_json::to_string_pretty(&json).unwrap());
} }

View File

@ -11,7 +11,7 @@ use collab_database::database::{
}; };
use collab_database::rows::{database_row_document_id_from_row_id, mut_row_with_collab, RowId}; use collab_database::rows::{database_row_document_id_from_row_id, mut_row_with_collab, RowId};
use collab_database::user::DatabaseWithViewsArray; use collab_database::user::DatabaseWithViewsArray;
use collab_folder::core::Folder; use collab_folder::{Folder, UserId};
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction}; use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
@ -22,7 +22,7 @@ use crate::migrations::MigrationUser;
/// Migration the collab objects of the old user to new user. Currently, it only happens when /// Migration the collab objects of the old user to new user. Currently, it only happens when
/// the user is a local user and try to use AppFlowy cloud service. /// the user is a local user and try to use AppFlowy cloud service.
pub fn migration_local_user_on_sign_up( pub fn migration_anon_user_on_sign_up(
old_user: &MigrationUser, old_user: &MigrationUser,
old_collab_db: &Arc<RocksCollabDB>, old_collab_db: &Arc<RocksCollabDB>,
new_user: &MigrationUser, new_user: &MigrationUser,
@ -207,7 +207,13 @@ where
old_folder_collab.with_origin_transact_mut(|txn| { old_folder_collab.with_origin_transact_mut(|txn| {
old_collab_r_txn.load_doc_with_txn(old_uid, old_workspace_id, txn) old_collab_r_txn.load_doc_with_txn(old_uid, old_workspace_id, txn)
})?; })?;
let old_folder = Folder::open(Arc::new(MutexCollab::from_collab(old_folder_collab)), None); let oid_user_id = UserId::from(old_uid);
let old_folder = Folder::open(
oid_user_id,
Arc::new(MutexCollab::from_collab(old_folder_collab)),
None,
)
.map_err(|err| PersistenceError::InvalidData(err.to_string()))?;
let mut folder_data = old_folder let mut folder_data = old_folder
.get_folder_data() .get_folder_data()
.ok_or(PersistenceError::Internal( .ok_or(PersistenceError::Internal(
@ -219,25 +225,13 @@ where
.insert(old_workspace_id.to_string(), new_workspace_id.to_string()); .insert(old_workspace_id.to_string(), new_workspace_id.to_string());
// 1. Replace the workspace views id to new id // 1. Replace the workspace views id to new id
debug_assert!(folder_data.workspaces.len() == 1); folder_data.workspace.id = new_workspace_id.clone();
folder_data folder_data
.workspaces .workspace
.child_views
.iter_mut() .iter_mut()
.enumerate() .for_each(|view_identifier| {
.for_each(|(index, workspace)| { view_identifier.id = old_to_new_id_map.get_new_id(&view_identifier.id);
if index == 0 {
workspace.id = new_workspace_id.to_string();
} else {
tracing::warn!("🔴migrate folder: more than one workspace");
workspace.id = old_to_new_id_map.get_new_id(&workspace.id);
}
workspace
.child_views
.iter_mut()
.for_each(|view_identifier| {
view_identifier.id = old_to_new_id_map.get_new_id(&view_identifier.id);
});
}); });
folder_data.views.iter_mut().for_each(|view| { folder_data.views.iter_mut().for_each(|view| {
@ -253,15 +247,6 @@ where
}); });
}); });
match old_to_new_id_map.get(&folder_data.current_workspace_id) {
Some(new_workspace_id) => {
folder_data.current_workspace_id = new_workspace_id.clone();
},
None => {
tracing::error!("🔴migrate folder: current workspace id not found");
},
}
match old_to_new_id_map.get(&folder_data.current_view) { match old_to_new_id_map.get(&folder_data.current_view) {
Some(new_view_id) => { Some(new_view_id) => {
folder_data.current_view = new_view_id.clone(); folder_data.current_view = new_view_id.clone();
@ -276,7 +261,8 @@ where
let new_folder_collab = Collab::new_with_raw_data(origin, new_workspace_id, vec![], vec![]) let new_folder_collab = Collab::new_with_raw_data(origin, new_workspace_id, vec![], vec![])
.map_err(|err| PersistenceError::Internal(Box::new(err)))?; .map_err(|err| PersistenceError::Internal(Box::new(err)))?;
let mutex_collab = Arc::new(MutexCollab::from_collab(new_folder_collab)); let mutex_collab = Arc::new(MutexCollab::from_collab(new_folder_collab));
let _ = Folder::create(mutex_collab.clone(), None, Some(folder_data)); let new_user_id = UserId::from(new_uid);
let _ = Folder::create(new_user_id, mutex_collab.clone(), None, folder_data);
{ {
let mutex_collab = mutex_collab.lock(); let mutex_collab = mutex_collab.lock();

View File

@ -0,0 +1,5 @@
pub use anon_user_data::*;
pub use sync_new_user::*;
mod anon_user_data;
mod sync_new_user;

View File

@ -10,7 +10,7 @@ use collab_database::database::get_database_row_ids;
use collab_database::rows::database_row_document_id_from_row_id; use collab_database::rows::database_row_document_id_from_row_id;
use collab_database::user::{get_database_with_views, DatabaseWithViews}; use collab_database::user::{get_database_with_views, DatabaseWithViews};
use collab_entity::{CollabObject, CollabType}; use collab_entity::{CollabObject, CollabType};
use collab_folder::core::{Folder, View, ViewLayout}; use collab_folder::{Folder, View, ViewLayout};
use parking_lot::Mutex; use parking_lot::Mutex;
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction}; use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
@ -255,9 +255,10 @@ async fn sync_folder(
let update = collab.encode_as_update_v1().0; let update = collab.encode_as_update_v1().0;
( (
MutexFolder::new(Folder::open( MutexFolder::new(Folder::open(
uid,
Arc::new(MutexCollab::from_collab(collab)), Arc::new(MutexCollab::from_collab(collab)),
None, None,
)), )?),
update, update,
) )
}; };

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use collab_database::database::WatchStream; use collab_database::database::WatchStream;
use collab_folder::core::FolderData; use collab_folder::FolderData;
use strum_macros::Display; use strum_macros::Display;
use flowy_derive::{Flowy_Event, ProtoBuf_Enum}; use flowy_derive::{Flowy_Event, ProtoBuf_Enum};

View File

@ -1,6 +1,7 @@
#[macro_use] #[macro_use]
extern crate flowy_sqlite; extern crate flowy_sqlite;
mod anon_user_upgrade;
pub mod entities; pub mod entities;
mod event_handler; mod event_handler;
pub mod event_map; pub mod event_map;

View File

@ -19,12 +19,12 @@ use flowy_user_deps::entities::*;
use lib_dispatch::prelude::af_spawn; use lib_dispatch::prelude::af_spawn;
use lib_infra::box_any::BoxAny; use lib_infra::box_any::BoxAny;
use crate::anon_user_upgrade::{migration_anon_user_on_sign_up, sync_user_data_to_cloud};
use crate::entities::{AuthStateChangedPB, AuthStatePB, UserProfilePB, UserSettingPB}; use crate::entities::{AuthStateChangedPB, AuthStatePB, UserProfilePB, UserSettingPB};
use crate::event_map::{DefaultUserStatusCallback, UserCloudServiceProvider, UserStatusCallback}; use crate::event_map::{DefaultUserStatusCallback, UserCloudServiceProvider, UserStatusCallback};
use crate::migrations::historical_document::HistoricalEmptyDocumentMigration; use crate::migrations::document_empty_content::HistoricalEmptyDocumentMigration;
use crate::migrations::migrate_to_new_user::migration_local_user_on_sign_up; use crate::migrations::migration::{UserDataMigration, UserLocalDataMigration};
use crate::migrations::migration::UserLocalDataMigration; use crate::migrations::workspace_and_favorite_v1::FavoriteV1AndWorkspaceArrayMigration;
use crate::migrations::sync_new_user::sync_user_data_to_cloud;
use crate::migrations::MigrationUser; use crate::migrations::MigrationUser;
use crate::services::cloud_config::get_cloud_config; use crate::services::cloud_config::get_cloud_config;
use crate::services::collab_interact::{CollabInteract, DefaultCollabInteract}; use crate::services::collab_interact::{CollabInteract, DefaultCollabInteract};
@ -165,8 +165,13 @@ impl UserManager {
self.database.get_pool(session.user_id), self.database.get_pool(session.user_id),
) { ) {
(Ok(collab_db), Ok(sqlite_pool)) => { (Ok(collab_db), Ok(sqlite_pool)) => {
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool) // ⚠The order of migrations is crucial. If you're adding a new migration, please ensure
.run(vec![Box::new(HistoricalEmptyDocumentMigration)]) // it's appended to the end of the list.
let migrations: Vec<Box<dyn UserDataMigration>> = vec![
Box::new(HistoricalEmptyDocumentMigration),
Box::new(FavoriteV1AndWorkspaceArrayMigration),
];
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool).run(migrations)
{ {
Ok(applied_migrations) => { Ok(applied_migrations) => {
if !applied_migrations.is_empty() { if !applied_migrations.is_empty() {
@ -358,12 +363,12 @@ impl UserManager {
}; };
event!( event!(
tracing::Level::INFO, tracing::Level::INFO,
"Migrate old user data from {:?} to {:?}", "Migrate anon user data from {:?} to {:?}",
old_user.user_profile.uid, old_user.user_profile.uid,
new_user.user_profile.uid new_user.user_profile.uid
); );
self self
.migrate_local_user_to_cloud(&old_user, &new_user) .migrate_anon_user_to_cloud(&old_user, &new_user)
.await?; .await?;
let _ = self.database.close(old_user.session.user_id); let _ = self.database.close(old_user.session.user_id);
} }
@ -689,14 +694,14 @@ impl UserManager {
Ok(()) Ok(())
} }
async fn migrate_local_user_to_cloud( async fn migrate_anon_user_to_cloud(
&self, &self,
old_user: &MigrationUser, old_user: &MigrationUser,
new_user: &MigrationUser, new_user: &MigrationUser,
) -> Result<(), FlowyError> { ) -> Result<(), FlowyError> {
let old_collab_db = self.database.get_collab_db(old_user.session.user_id)?; 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)?; let new_collab_db = self.database.get_collab_db(new_user.session.user_id)?;
migration_local_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)?;
if let Err(err) = sync_user_data_to_cloud( if let Err(err) = sync_user_data_to_cloud(
self.cloud_services.get_user_service()?, self.cloud_services.get_user_service()?,

View File

@ -4,7 +4,7 @@ use collab::core::collab::MutexCollab;
use collab::core::origin::{CollabClient, CollabOrigin}; use collab::core::origin::{CollabClient, CollabOrigin};
use collab_document::document::Document; use collab_document::document::Document;
use collab_document::document_data::default_document_data; use collab_document::document_data::default_document_data;
use collab_folder::core::Folder; use collab_folder::Folder;
use collab_integrate::{RocksCollabDB, YrsDocAction}; use collab_integrate::{RocksCollabDB, YrsDocAction};
use flowy_error::{internal_error, FlowyResult}; use flowy_error::{internal_error, FlowyResult};
@ -25,8 +25,13 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
if let Ok(updates) = write_txn.get_all_updates(session.user_id, &session.user_workspace.id) { if let Ok(updates) = write_txn.get_all_updates(session.user_id, &session.user_workspace.id) {
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom")); let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
// Deserialize the folder from the raw data // Deserialize the folder from the raw data
let folder = let folder = Folder::from_collab_raw_data(
Folder::from_collab_raw_data(origin.clone(), updates, &session.user_workspace.id, vec![])?; session.user_id,
origin.clone(),
updates,
&session.user_workspace.id,
vec![],
)?;
// Migration the first level documents of the workspace // Migration the first level documents of the workspace
let migration_views = folder.get_workspace_views(&session.user_workspace.id); let migration_views = folder.get_workspace_views(&session.user_workspace.id);

View File

@ -2,6 +2,7 @@ use std::sync::Arc;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::{RunQueryDsl, SqliteConnection}; use diesel::{RunQueryDsl, SqliteConnection};
use tracing::event;
use collab_integrate::RocksCollabDB; use collab_integrate::RocksCollabDB;
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -54,6 +55,12 @@ impl UserLocalDataMigration {
{ {
let migration_name = migration.name().to_string(); let migration_name = migration.name().to_string();
if !duplicated_names.contains(&migration_name) { if !duplicated_names.contains(&migration_name) {
event!(
tracing::Level::INFO,
"Running migration {}",
migration.name()
);
migration.run(&self.session, &self.collab_db)?; migration.run(&self.session, &self.collab_db)?;
applied_migrations.push(migration.name().to_string()); applied_migrations.push(migration.name().to_string());
save_record(&conn, &migration_name); save_record(&conn, &migration_name);

View File

@ -1,7 +1,6 @@
pub use define::*; pub use define::*;
mod define; mod define;
pub mod historical_document; pub mod document_empty_content;
pub mod migrate_to_new_user;
pub mod migration; pub mod migration;
pub mod sync_new_user; pub mod workspace_and_favorite_v1;

View File

@ -0,0 +1,55 @@
use std::sync::Arc;
use collab::core::origin::{CollabClient, CollabOrigin};
use collab_folder::Folder;
use collab_integrate::{RocksCollabDB, YrsDocAction};
use flowy_error::{internal_error, FlowyResult};
use crate::migrations::migration::UserDataMigration;
use crate::services::entities::Session;
/// 1. Migrate the workspace: { favorite: [view_id] } to { favorite: { uid: [view_id] } }
/// 2. Migrate { workspaces: [workspace object] } to { views: { workspace object } }. Make each folder
/// only have one workspace.
pub struct FavoriteV1AndWorkspaceArrayMigration;
impl UserDataMigration for FavoriteV1AndWorkspaceArrayMigration {
fn name(&self) -> &str {
"workspace_favorite_v1_and_workspace_array_migration"
}
fn run(&self, session: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()> {
let write_txn = collab_db.write_txn();
if let Ok(updates) = write_txn.get_all_updates(session.user_id, &session.user_workspace.id) {
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
// Deserialize the folder from the raw data
let folder = Folder::from_collab_raw_data(
session.user_id,
origin,
updates,
&session.user_workspace.id,
vec![],
)?;
folder.migrate_workspace_to_view();
let favorite_view_ids = folder
.get_favorite_v1()
.into_iter()
.map(|fav| fav.id)
.collect::<Vec<String>>();
if !favorite_view_ids.is_empty() {
folder.add_favorites(favorite_view_ids);
}
let (doc_state, sv) = folder.encode_as_update_v1();
write_txn
.flush_doc_with(session.user_id, &session.user_workspace.id, &doc_state, &sv)
.map_err(internal_error)?;
write_txn.commit_transaction().map_err(internal_error)?;
}
Ok(())
}
}