Browse Source

refactor: folder with yrs

* feat: try using folder2

* feat: update

* feat: implement handlers

* fix: compile errors

* chore: add unsafe send + sync

* feat: remove unsafe impl

* fix: replace folder with foler2

* chore: dart compile errors

* test: fix test

* test: fix test

* test: bypass existing tests

* feat: open latest view

* chore: fix dart warnings

* chore: config notification

* fix: folder notification  bugs

* fix: doesn't open the new view after creating

* chore: rename struct

* refactor: user id

* test: fix test

* chore: remove unused user_id

* fix: fix read workspace views

* chore: rename appflowy data folder

* chore: update ref

* fix: tauri build
Nathan.fooo 2 years ago
parent
commit
e1c8135f5d
100 changed files with 1189 additions and 668 deletions
  1. 1 1
      frontend/appflowy_flutter/lib/core/folder_notification.dart
  2. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart
  3. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart
  4. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart
  5. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart
  6. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart
  7. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart
  8. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart
  9. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/calendar/presentation/calendar_page.dart
  10. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_bloc.dart
  11. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart
  12. 1 1
      frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart
  13. 2 4
      frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart
  14. 1 1
      frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart
  15. 1 1
      frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart
  16. 1 1
      frontend/appflowy_flutter/lib/plugins/document/application/share_service.dart
  17. 1 1
      frontend/appflowy_flutter/lib/plugins/document/document.dart
  18. 1 1
      frontend/appflowy_flutter/lib/plugins/document/document_page.dart
  19. 2 2
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart
  20. 2 3
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart
  21. 12 13
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart
  22. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart
  23. 4 5
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart
  24. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart
  25. 4 5
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart
  26. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_button.dart
  27. 2 3
      frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart
  28. 6 3
      frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart
  29. 4 7
      frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart
  30. 1 1
      frontend/appflowy_flutter/lib/plugins/trash/src/trash_cell.dart
  31. 1 1
      frontend/appflowy_flutter/lib/plugins/util.dart
  32. 1 8
      frontend/appflowy_flutter/lib/startup/deps_resolver.dart
  33. 1 1
      frontend/appflowy_flutter/lib/startup/plugin/plugin.dart
  34. 2 2
      frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart
  35. 2 9
      frontend/appflowy_flutter/lib/user/application/user_listener.dart
  36. 3 2
      frontend/appflowy_flutter/lib/user/application/user_service.dart
  37. 1 1
      frontend/appflowy_flutter/lib/user/presentation/router.dart
  38. 1 1
      frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart
  39. 1 1
      frontend/appflowy_flutter/lib/user/presentation/welcome_screen.dart
  40. 17 18
      frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart
  41. 9 9
      frontend/appflowy_flutter/lib/workspace/application/app/app_listener.dart
  42. 30 30
      frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart
  43. 2 2
      frontend/appflowy_flutter/lib/workspace/application/home/home_bloc.dart
  44. 4 4
      frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart
  45. 1 1
      frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart
  46. 25 27
      frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart
  47. 1 1
      frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart
  48. 1 1
      frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart
  49. 12 12
      frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart
  50. 1 1
      frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart
  51. 1 1
      frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart
  52. 2 2
      frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart
  53. 1 1
      frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart
  54. 1 1
      frontend/appflowy_flutter/lib/workspace/application/workspace/welcome_bloc.dart
  55. 6 6
      frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart
  56. 16 10
      frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart
  57. 3 3
      frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart
  58. 1 1
      frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart
  59. 5 5
      frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart
  60. 6 6
      frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/menu_app.dart
  61. 1 1
      frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/section/item.dart
  62. 3 3
      frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu.dart
  63. 6 6
      frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart
  64. 1 1
      frontend/appflowy_flutter/lib/workspace/presentation/widgets/left_bar_item.dart
  65. 2 2
      frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart
  66. 1 1
      frontend/appflowy_flutter/test/bloc_test/board_test/util.dart
  67. 1 1
      frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart
  68. 10 10
      frontend/appflowy_flutter/test/bloc_test/home_test/app_bloc_test.dart
  69. 5 5
      frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart
  70. 1 1
      frontend/appflowy_flutter/test/bloc_test/home_test/home_bloc_test.dart
  71. 4 4
      frontend/appflowy_flutter/test/bloc_test/home_test/menu_bloc_test.dart
  72. 8 9
      frontend/appflowy_flutter/test/bloc_test/home_test/trash_bloc_test.dart
  73. 3 3
      frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart
  74. 4 4
      frontend/appflowy_flutter/test/util.dart
  75. 285 82
      frontend/appflowy_tauri/src-tauri/Cargo.lock
  76. 7 0
      frontend/appflowy_tauri/src-tauri/Cargo.toml
  77. 2 2
      frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts
  78. 2 2
      frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts
  79. 5 5
      frontend/appflowy_tauri/src/appflowy_app/components/layout/Workspace.hooks.ts
  80. 2 2
      frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts
  81. 4 4
      frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts
  82. 0 129
      frontend/appflowy_tauri/src/appflowy_app/components/tests/TestApiButton.tsx
  83. 1 1
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts
  84. 1 1
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_bd_svc.ts
  85. 14 15
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts
  86. 5 5
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts
  87. 1 1
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_bd_svc.ts
  88. 13 6
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts
  89. 12 4
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts
  90. 2 2
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts
  91. 2 2
      frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts
  92. 1 1
      frontend/appflowy_tauri/src/services/backend/index.ts
  93. 244 55
      frontend/rust-lib/Cargo.lock
  94. 9 2
      frontend/rust-lib/Cargo.toml
  95. 4 0
      frontend/rust-lib/flowy-core/Cargo.toml
  96. 1 1
      frontend/rust-lib/flowy-core/src/deps_resolve/document_deps.rs
  97. 258 0
      frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs
  98. 1 1
      frontend/rust-lib/flowy-core/src/deps_resolve/grid_deps.rs
  99. 2 2
      frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs
  100. 44 58
      frontend/rust-lib/flowy-core/src/lib.rs

+ 1 - 1
frontend/appflowy_flutter/lib/core/folder_notification.dart

@@ -3,7 +3,7 @@ import 'dart:typed_data';
 import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart';
 import 'package:appflowy_backend/rust_stream.dart';
 
 import 'notification_helper.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart

@@ -9,7 +9,7 @@ import 'package:appflowy_backend/protobuf/flowy-database/group_changeset.pb.dart
 import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:collection/collection.dart';
 import 'dart:async';
 import 'package:dartz/dartz.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart

@@ -5,7 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pb.dar
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/group.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart

@@ -6,7 +6,7 @@ import 'package:dartz/dartz.dart';
 import 'package:equatable/equatable.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart

@@ -3,7 +3,7 @@ import 'package:appflowy/plugins/util.dart';
 import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
 import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart

@@ -7,7 +7,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle
 import 'package:appflowy/plugins/database_view/application/row/row_cache.dart';
 import 'package:appflowy/plugins/database_view/application/row/row_data_controller.dart';
 import 'package:appflowy/plugins/database_view/widgets/row/row_detail.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
 import 'package:appflowy_board/appflowy_board.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart

@@ -3,7 +3,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
 import 'package:calendar_view/calendar_view.dart';
 import 'package:dartz/dartz.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart

@@ -3,7 +3,7 @@ import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
 import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 
 import '../../util.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/calendar/presentation/calendar_page.dart

@@ -1,6 +1,6 @@
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/plugins/database_view/calendar/application/calendar_bloc.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:calendar_view/calendar_view.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_bloc.dart

@@ -4,7 +4,7 @@ import 'package:appflowy/plugins/database_view/application/row/row_service.dart'
 import 'package:dartz/dartz.dart';
 import 'package:equatable/equatable.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart

@@ -4,7 +4,7 @@ import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
 import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 
 import 'presentation/grid_page.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart

@@ -8,7 +8,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 import 'package:linked_scroll_controller/linked_scroll_controller.dart';

+ 2 - 4
frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart

@@ -8,9 +8,8 @@ import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pbserver.dart';
 import 'package:appflowy_editor/appflowy_editor.dart'
     show EditorState, Document, Transaction, Node;
-import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -49,8 +48,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
           emit(state.copyWith(isDeleted: false));
         },
         deletePermanently: (DeletePermanently value) async {
-          final result = await _trashService
-              .deleteViews([Tuple2(view.id, TrashType.TrashView)]);
+          final result = await _trashService.deleteViews([view.id]);
 
           final newState = result.fold(
               (l) => state.copyWith(forceClose: true), (r) => state);

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart

@@ -1,7 +1,7 @@
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
 

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart

@@ -5,7 +5,7 @@ import 'package:appflowy/plugins/document/presentation/plugins/parsers/divider_n
 import 'package:appflowy/plugins/document/presentation/plugins/parsers/math_equation_node_parser.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/parsers/code_block_node_parser.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/application/share_service.dart

@@ -3,7 +3,7 @@ import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 
 class ShareService {
   Future<Either<ExportDataPB, FlowyError>> export(

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/document.dart

@@ -10,7 +10,7 @@ import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
 import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/document_page.dart

@@ -1,5 +1,5 @@
 import 'package:appflowy/plugins/document/presentation/plugins/board/board_view_menu_item.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart';

+ 2 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart

@@ -3,7 +3,7 @@ import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/workspace/application/app/app_service.dart';
 import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:dartz/dartz.dart' as dartz;
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -59,7 +59,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
           child: CircularProgressIndicator(),
         );
       },
-      future: AppBackendService().getView(appID, gridID),
+      future: AppBackendService().getChildView(appID, gridID),
     );
   }
 

+ 2 - 3
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart

@@ -1,14 +1,13 @@
 import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/grid/grid_node_widget.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 
 const String kAppID = 'app_id';
 const String kViewID = 'view_id';
 
 extension InsertPage on EditorState {
-  void insertPage(AppPB appPB, ViewPB viewPB) {
+  void insertPage(ViewPB appPB, ViewPB viewPB) {
     final selection = service.selectionService.currentSelection.value;
     final textNodes =
         service.selectionService.currentSelectedNodes.whereType<TextNode>();

+ 12 - 13
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart

@@ -1,6 +1,5 @@
 import 'package:appflowy/workspace/application/app/app_service.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:dartz/dartz.dart' as dartz;
 import 'package:flowy_infra/image.dart';
@@ -50,8 +49,8 @@ void showLinkToPageMenu(
           editorState: editorState,
           layoutType: pageType,
           hintText: hintText,
-          onSelected: (appPB, viewPB) {
-            editorState.insertPage(appPB, viewPB);
+          onSelected: (viewPB, childViewPB) {
+            editorState.insertPage(viewPB, childViewPB);
           },
         ),
       ),
@@ -85,7 +84,7 @@ class LinkToPageMenu extends StatefulWidget {
   final EditorState editorState;
   final ViewLayoutTypePB layoutType;
   final String hintText;
-  final void Function(AppPB appPB, ViewPB viewPB) onSelected;
+  final void Function(ViewPB view, ViewPB childView) onSelected;
 
   @override
   State<LinkToPageMenu> createState() => _LinkToPageMenuState();
@@ -118,11 +117,11 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
   }
 
   Widget _buildListWidget(BuildContext context) {
-    return FutureBuilder<List<dartz.Tuple2<AppPB, List<ViewPB>>>>(
+    return FutureBuilder<List<dartz.Tuple2<ViewPB, List<ViewPB>>>>(
       builder: (context, snapshot) {
         if (snapshot.hasData &&
             snapshot.connectionState == ConnectionState.done) {
-          final apps = snapshot.data;
+          final views = snapshot.data;
           final children = <Widget>[
             Padding(
               padding: const EdgeInsets.symmetric(vertical: 4),
@@ -133,18 +132,18 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
               ),
             ),
           ];
-          if (apps != null && apps.isNotEmpty) {
-            for (final app in apps) {
-              if (app.value2.isNotEmpty) {
+          if (views != null && views.isNotEmpty) {
+            for (final view in views) {
+              if (view.value2.isNotEmpty) {
                 children.add(
                   Padding(
                     padding: const EdgeInsets.symmetric(vertical: 4),
                     child: FlowyText.regular(
-                      app.value1.name,
+                      view.value1.name,
                     ),
                   ),
                 );
-                for (final value in app.value2) {
+                for (final value in view.value2) {
                   children.add(
                     FlowyButton(
                       leftIcon: svgWidget(
@@ -152,7 +151,7 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
                         color: Theme.of(context).iconTheme.color,
                       ),
                       text: FlowyText.regular(value.name),
-                      onTap: () => widget.onSelected(app.value1, value),
+                      onTap: () => widget.onSelected(view.value1, value),
                     ),
                   );
                 }

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart

@@ -1,6 +1,6 @@
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/base/link_to_page_widget.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';

+ 4 - 5
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/plugins/document/application/prelude.dart';
@@ -42,15 +42,14 @@ SelectionMenuItem boardViewMenuItem(DocumentBloc documentBloc) =>
           return;
         }
 
-        final app =
-            (await service.readApp(appId: result.appId)).getLeftOrNull();
+        final app = (await service.getView(result.viewId)).getLeftOrNull();
         // We should show an error dialog.
         if (app == null) {
           return;
         }
 
-        final view =
-            (await service.getView(result.appId, result.id)).getLeftOrNull();
+        final view = (await service.getChildView(result.viewId, result.id))
+            .getLeftOrNull();
         // As this.
         if (view == null) {
           return;

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart

@@ -1,6 +1,6 @@
 import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/base/link_to_page_widget.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';

+ 4 - 5
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart

@@ -2,7 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/plugins/document/application/doc_bloc.dart';
 import 'package:appflowy/plugins/document/presentation/plugins/base/insert_page_command.dart';
 import 'package:appflowy/workspace/application/app/app_service.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
@@ -41,15 +41,14 @@ SelectionMenuItem gridViewMenuItem(DocumentBloc documentBloc) =>
           return;
         }
 
-        final app =
-            (await service.readApp(appId: result.appId)).getLeftOrNull();
+        final app = (await service.getView(result.viewId)).getLeftOrNull();
         // We should show an error dialog.
         if (app == null) {
           return;
         }
 
-        final view =
-            (await service.getView(result.appId, result.id)).getLeftOrNull();
+        final view = (await service.getChildView(result.viewId, result.id))
+            .getLeftOrNull();
         // As this.
         if (view == null) {
           return;

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_button.dart

@@ -13,7 +13,7 @@ import 'package:file_picker/file_picker.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 2 - 3
frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart

@@ -1,6 +1,6 @@
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -31,8 +31,7 @@ class TrashBloc extends Bloc<TrashEvent, TrashState> {
         final result = await _service.putback(e.trashId);
         await _handleResult(result, emit);
       }, delete: (e) async {
-        final result =
-            await _service.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
+        final result = await _service.deleteViews([e.trash.id]);
         await _handleResult(result, emit);
       }, deleteAll: (e) async {
         final result = await _service.deleteAll();

+ 6 - 3
frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart

@@ -3,9 +3,9 @@ import 'dart:typed_data';
 import 'package:appflowy/core/folder_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart';
 import 'package:appflowy_backend/rust_stream.dart';
 
 typedef TrashUpdatedCallback = void Function(
@@ -19,7 +19,10 @@ class TrashListener {
 
   void start({TrashUpdatedCallback? trashUpdated}) {
     _trashUpdated = trashUpdated;
-    _parser = FolderNotificationParser(callback: _observableCallback);
+    _parser = FolderNotificationParser(
+      id: "trash",
+      callback: _observableCallback,
+    );
     _subscription =
         RustStreamReceiver.listen((observable) => _parser?.parse(observable));
   }

+ 4 - 7
frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart

@@ -2,7 +2,7 @@ import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart';
 
 class TrashService {
   Future<Either<RepeatedTrashPB, FlowyError>> readTrash() {
@@ -15,12 +15,9 @@ class TrashService {
     return FolderEventPutbackTrash(id).send();
   }
 
-  Future<Either<Unit, FlowyError>> deleteViews(
-      List<Tuple2<String, TrashType>> trashList) {
-    final items = trashList.map((trash) {
-      return TrashIdPB.create()
-        ..id = trash.value1
-        ..ty = trash.value2;
+  Future<Either<Unit, FlowyError>> deleteViews(List<String> trash) {
+    final items = trash.map((trash) {
+      return TrashIdPB.create()..id = trash;
     });
 
     final ids = RepeatedTrashIdPB(items: items);

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/trash/src/trash_cell.dart

@@ -2,7 +2,7 @@ import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:intl/intl.dart';
 import 'package:fixnum/fixnum.dart' as $fixnum;

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/util.dart

@@ -2,7 +2,7 @@ import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/workspace/application/view/view_listener.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 
 class ViewPluginNotifier extends PluginNotifier<Option<DeletedViewPB>> {

+ 1 - 8
frontend/appflowy_flutter/lib/startup/deps_resolver.dart

@@ -8,7 +8,6 @@ import 'package:appflowy/user/application/user_listener.dart';
 import 'package:appflowy/user/application/user_service.dart';
 import 'package:appflowy/util/file_picker/file_picker_impl.dart';
 import 'package:appflowy/util/file_picker/file_picker_service.dart';
-import 'package:appflowy/workspace/application/app/prelude.dart';
 import 'package:appflowy/plugins/document/application/prelude.dart';
 import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
 import 'package:appflowy/workspace/application/user/prelude.dart';
@@ -22,8 +21,7 @@ import 'package:appflowy/user/presentation/router.dart';
 import 'package:appflowy/plugins/trash/application/prelude.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
 import 'package:appflowy/workspace/presentation/home/menu/menu.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:fluttertoast/fluttertoast.dart';
 import 'package:get_it/get_it.dart';
@@ -122,11 +120,6 @@ void _resolveFolderDeps(GetIt getIt) {
     (user, _) => SettingsUserViewBloc(user),
   );
 
-  // AppPB
-  getIt.registerFactoryParam<AppBloc, AppPB, void>(
-    (app, _) => AppBloc(app: app),
-  );
-
   // trash
   getIt.registerLazySingleton<TrashService>(() => TrashService());
   getIt.registerLazySingleton<TrashListener>(() => TrashListener());

+ 1 - 1
frontend/appflowy_flutter/lib/startup/plugin/plugin.dart

@@ -3,7 +3,7 @@ library flowy_plugin;
 import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/widgets.dart';
 
 export "./src/sandbox.dart";

+ 2 - 2
frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart

@@ -36,10 +36,10 @@ Future<Directory> appFlowyDocumentDirectory() async {
   switch (integrationEnv()) {
     case IntegrationMode.develop:
       Directory documentsDir = await getApplicationDocumentsDirectory();
-      return Directory(path.join(documentsDir.path, 'flowy_dev')).create();
+      return Directory(path.join(documentsDir.path, 'data_dev')).create();
     case IntegrationMode.release:
       Directory documentsDir = await getApplicationDocumentsDirectory();
-      return Directory(path.join(documentsDir.path, 'flowy')).create();
+      return Directory(path.join(documentsDir.path, 'data')).create();
     case IntegrationMode.test:
       return Directory(path.join(Directory.current.path, '.sandbox'));
   }

+ 2 - 9
frontend/appflowy_flutter/lib/user/application/user_listener.dart

@@ -2,12 +2,12 @@ import 'dart:async';
 import 'package:appflowy/core/folder_notification.dart';
 import 'package:appflowy/core/user_notification.dart';
 import 'package:dartz/dartz.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'dart:typed_data';
 import 'package:flowy_infra/notifier.dart';
 import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/notification.pb.dart'
     as user;
@@ -119,13 +119,6 @@ class UserWorkspaceListener {
   ) {
     switch (ty) {
       case FolderNotification.DidCreateWorkspace:
-      case FolderNotification.DidDeleteWorkspace:
-        result.fold(
-          (payload) => _workspacesChangedNotifier?.value =
-              left(RepeatedWorkspacePB.fromBuffer(payload).items),
-          (error) => _workspacesChangedNotifier?.value = right(error),
-        );
-        break;
       case FolderNotification.DidUpdateWorkspaceSetting:
         result.fold(
           (payload) => _settingChangedNotifier?.value =

+ 3 - 2
frontend/appflowy_flutter/lib/user/application/user_service.dart

@@ -3,15 +3,16 @@ import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.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:fixnum/fixnum.dart';
 
 class UserBackendService {
   UserBackendService({
     required this.userId,
   });
 
-  final String userId;
+  final Int64 userId;
 
   static Future<Either<UserProfilePB, FlowyError>> getCurrentUserProfile() {
     return UserEventGetUserProfile().send();

+ 1 - 1
frontend/appflowy_flutter/lib/user/presentation/router.dart

@@ -10,7 +10,7 @@ import 'package:flowy_infra/time/duration.dart';
 import 'package:flowy_infra_ui/widget/route/animation.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
     show UserProfilePB;
-import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
 import 'package:flutter/material.dart';
 
 class AuthRouter {

+ 1 - 1
frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart

@@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:url_launcher/url_launcher.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/user/presentation/welcome_screen.dart

@@ -5,7 +5,7 @@ import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.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:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 17 - 18
frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart

@@ -7,8 +7,7 @@ import 'package:appflowy/workspace/application/app/app_service.dart';
 import 'package:appflowy/workspace/presentation/home/menu/menu.dart';
 import 'package:expandable/expandable.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -21,10 +20,10 @@ class AppBloc extends Bloc<AppEvent, AppState> {
   final AppBackendService appService;
   final AppListener appListener;
 
-  AppBloc({required AppPB app})
+  AppBloc({required ViewPB view})
       : appService = AppBackendService(),
-        appListener = AppListener(appId: app.id),
-        super(AppState.initial(app)) {
+        appListener = AppListener(viewId: view.id),
+        super(AppState.initial(view)) {
     on<AppEvent>((event, emit) async {
       await event.map(initial: (e) async {
         _startListening();
@@ -41,10 +40,10 @@ class AppBloc extends Bloc<AppEvent, AppState> {
         await _renameView(e, emit);
       }, appDidUpdate: (e) async {
         final latestCreatedView = state.latestCreatedView;
-        final views = e.app.belongings.items;
+        final views = e.app.belongings;
         AppState newState = state.copyWith(
           views: views,
-          app: e.app,
+          view: e.app,
         );
         if (latestCreatedView != null) {
           final index =
@@ -70,7 +69,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
 
   Future<void> _renameView(Rename e, Emitter<AppState> emit) async {
     final result =
-        await appService.updateApp(appId: state.app.id, name: e.newName);
+        await appService.updateApp(appId: state.view.id, name: e.newName);
     result.fold(
       (l) => emit(state.copyWith(successOrFailure: left(unit))),
       (error) => emit(state.copyWith(successOrFailure: right(error))),
@@ -79,7 +78,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
 
 // Delete the current app
   Future<void> _deleteApp(Emitter<AppState> emit) async {
-    final result = await appService.delete(appId: state.app.id);
+    final result = await appService.delete(viewId: state.view.id);
     result.fold(
       (unit) => emit(state.copyWith(successOrFailure: left(unit))),
       (error) => emit(state.copyWith(successOrFailure: right(error))),
@@ -96,7 +95,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
 
   Future<void> _createView(CreateView value, Emitter<AppState> emit) async {
     final result = await appService.createView(
-      appId: state.app.id,
+      appId: state.view.id,
       name: value.name,
       desc: value.desc ?? "",
       layoutType: value.pluginBuilder.layoutType!,
@@ -122,7 +121,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
   }
 
   Future<void> _loadViews(Emitter<AppState> emit) async {
-    final viewsOrFailed = await appService.getViews(appId: state.app.id);
+    final viewsOrFailed = await appService.getViews(viewId: state.view.id);
     viewsOrFailed.fold(
       (views) => emit(state.copyWith(views: views)),
       (error) {
@@ -150,34 +149,34 @@ class AppEvent with _$AppEvent {
   const factory AppEvent.delete() = DeleteApp;
   const factory AppEvent.deleteView(String viewId) = DeleteView;
   const factory AppEvent.rename(String newName) = Rename;
-  const factory AppEvent.appDidUpdate(AppPB app) = AppDidUpdate;
+  const factory AppEvent.appDidUpdate(ViewPB app) = AppDidUpdate;
 }
 
 @freezed
 class AppState with _$AppState {
   const factory AppState({
-    required AppPB app,
+    required ViewPB view,
     required List<ViewPB> views,
     ViewPB? latestCreatedView,
     required Either<Unit, FlowyError> successOrFailure,
   }) = _AppState;
 
-  factory AppState.initial(AppPB app) => AppState(
-        app: app,
-        views: app.belongings.items,
+  factory AppState.initial(ViewPB view) => AppState(
+        view: view,
+        views: view.belongings,
         successOrFailure: left(unit),
       );
 }
 
 class AppViewDataContext extends ChangeNotifier {
-  final String appId;
+  final String viewId;
   final ValueNotifier<List<ViewPB>> _viewsNotifier = ValueNotifier([]);
   final ValueNotifier<ViewPB?> _selectedViewNotifier = ValueNotifier(null);
   VoidCallback? _menuSharedStateListener;
   ExpandableController expandController =
       ExpandableController(initialExpanded: false);
 
-  AppViewDataContext({required this.appId}) {
+  AppViewDataContext({required this.viewId}) {
     _setLatestView(getIt<MenuSharedState>().latestOpenView);
     _menuSharedStateListener =
         getIt<MenuSharedState>().addLatestViewListener((view) {

+ 9 - 9
frontend/appflowy_flutter/lib/workspace/application/app/app_listener.dart

@@ -5,12 +5,11 @@ import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart';
 import 'package:appflowy_backend/rust_stream.dart';
 
-typedef AppDidUpdateCallback = void Function(AppPB app);
+typedef AppDidUpdateCallback = void Function(ViewPB app);
 typedef ViewsDidChangeCallback = void Function(
     Either<List<ViewPB>, FlowyError> viewsOrFailed);
 
@@ -18,15 +17,15 @@ class AppListener {
   StreamSubscription<SubscribeObject>? _subscription;
   AppDidUpdateCallback? _updated;
   FolderNotificationParser? _parser;
-  String appId;
+  String viewId;
 
   AppListener({
-    required this.appId,
+    required this.viewId,
   });
 
   void start({AppDidUpdateCallback? onAppUpdated}) {
     _updated = onAppUpdated;
-    _parser = FolderNotificationParser(id: appId, callback: _handleCallback);
+    _parser = FolderNotificationParser(id: viewId, callback: _handleCallback);
     _subscription =
         RustStreamReceiver.listen((observable) => _parser?.parse(observable));
   }
@@ -34,11 +33,12 @@ class AppListener {
   void _handleCallback(
       FolderNotification ty, Either<Uint8List, FlowyError> result) {
     switch (ty) {
-      case FolderNotification.DidUpdateApp:
+      case FolderNotification.DidUpdateView:
+      case FolderNotification.DidUpdateChildViews:
         if (_updated != null) {
           result.fold(
             (payload) {
-              final app = AppPB.fromBuffer(payload);
+              final app = ViewPB.fromBuffer(payload);
               _updated!(app);
             },
             (error) => Log.error(error),

+ 30 - 30
frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart

@@ -1,20 +1,13 @@
 import 'dart:async';
 import 'dart:convert';
 
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 
 class AppBackendService {
-  Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
-    final payload = AppIdPB.create()..value = appId;
-
-    return FolderEventReadApp(payload).send();
-  }
-
   Future<Either<ViewPB, FlowyError>> createView({
     required String appId,
     required String name,
@@ -51,20 +44,20 @@ class AppBackendService {
     return FolderEventCreateView(payload).send();
   }
 
-  Future<Either<List<ViewPB>, FlowyError>> getViews({required String appId}) {
-    final payload = AppIdPB.create()..value = appId;
+  Future<Either<List<ViewPB>, FlowyError>> getViews({required String viewId}) {
+    final payload = ViewIdPB.create()..value = viewId;
 
-    return FolderEventReadApp(payload).send().then((result) {
+    return FolderEventReadView(payload).send().then((result) {
       return result.fold(
-        (app) => left(app.belongings.items),
+        (app) => left(app.belongings),
         (error) => right(error),
       );
     });
   }
 
-  Future<Either<Unit, FlowyError>> delete({required String appId}) {
-    final request = AppIdPB.create()..value = appId;
-    return FolderEventDeleteApp(request).send();
+  Future<Either<Unit, FlowyError>> delete({required String viewId}) {
+    final request = RepeatedViewIdPB.create()..items.add(viewId);
+    return FolderEventDeleteView(request).send();
   }
 
   Future<Either<Unit, FlowyError>> deleteView({required String viewId}) {
@@ -72,14 +65,14 @@ class AppBackendService {
     return FolderEventDeleteView(request).send();
   }
 
-  Future<Either<Unit, FlowyError>> updateApp(
+  Future<Either<ViewPB, FlowyError>> updateApp(
       {required String appId, String? name}) {
-    UpdateAppPayloadPB payload = UpdateAppPayloadPB.create()..appId = appId;
+    var payload = UpdateViewPayloadPB.create()..viewId = appId;
 
     if (name != null) {
       payload.name = name;
     }
-    return FolderEventUpdateApp(payload).send();
+    return FolderEventUpdateView(payload).send();
   }
 
   Future<Either<Unit, FlowyError>> moveView({
@@ -96,22 +89,22 @@ class AppBackendService {
     return FolderEventMoveItem(payload).send();
   }
 
-  Future<List<Tuple2<AppPB, List<ViewPB>>>> fetchViews(
+  Future<List<Tuple2<ViewPB, List<ViewPB>>>> fetchViews(
       ViewLayoutTypePB layoutType) async {
-    final result = <Tuple2<AppPB, List<ViewPB>>>[];
+    final result = <Tuple2<ViewPB, List<ViewPB>>>[];
     return FolderEventReadCurrentWorkspace().send().then((value) async {
       final workspaces = value.getLeftOrNull<WorkspaceSettingPB>();
       if (workspaces != null) {
-        final apps = workspaces.workspace.apps.items;
-        for (var app in apps) {
-          final views = await getViews(appId: app.id).then(
+        final views = workspaces.workspace.views;
+        for (var view in views) {
+          final childViews = await getViews(viewId: view.id).then(
             (value) => value
                 .getLeftOrNull<List<ViewPB>>()
                 ?.where((e) => e.layout == layoutType)
                 .toList(),
           );
-          if (views != null && views.isNotEmpty) {
-            result.add(Tuple2(app, views));
+          if (childViews != null && childViews.isNotEmpty) {
+            result.add(Tuple2(view, childViews));
           }
         }
       }
@@ -120,14 +113,21 @@ class AppBackendService {
   }
 
   Future<Either<ViewPB, FlowyError>> getView(
-    String appID,
     String viewID,
   ) async {
-    final payload = AppIdPB.create()..value = appID;
-    return FolderEventReadApp(payload).send().then((result) {
+    final payload = ViewIdPB.create()..value = viewID;
+    return FolderEventReadView(payload).send();
+  }
+
+  Future<Either<ViewPB, FlowyError>> getChildView(
+    String viewID,
+    String childViewID,
+  ) async {
+    final payload = ViewIdPB.create()..value = viewID;
+    return FolderEventReadView(payload).send().then((result) {
       return result.fold(
         (app) => left(
-          app.belongings.items.firstWhere((e) => e.id == viewID),
+          app.belongings.firstWhere((e) => e.id == childViewID),
         ),
         (error) => right(error),
       );

+ 2 - 2
frontend/appflowy_flutter/lib/workspace/application/home/home_bloc.dart

@@ -3,8 +3,8 @@ import 'package:flowy_infra/time/duration.dart';
 import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'
     show WorkspaceSettingPB;
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 4 - 4
frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart

@@ -1,14 +1,14 @@
 import 'dart:async';
 
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
 
 class HomeService {
-  Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
-    final payload = AppIdPB.create()..value = appId;
+  Future<Either<ViewPB, FlowyError>> readApp({required String appId}) {
+    final payload = ViewIdPB.create()..value = appId;
 
-    return FolderEventReadApp(payload).send();
+    return FolderEventReadView(payload).send();
   }
 }

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:appflowy/user/application/user_listener.dart';
 import 'package:appflowy/workspace/application/appearance.dart';
 import 'package:appflowy/workspace/application/edit_panel/edit_context.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'
     show WorkspaceSettingPB;
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:dartz/dartz.dart';

+ 25 - 27
frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart

@@ -2,11 +2,11 @@ import 'dart:async';
 import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:appflowy/workspace/application/workspace/workspace_listener.dart';
 import 'package:appflowy/workspace/application/workspace/workspace_service.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.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:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -38,24 +38,35 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
           emit(state.copyWith(plugin: e.plugin));
         },
         createApp: (_CreateApp event) async {
-          await _performActionOnCreateApp(event, emit);
+          final result = await _workspaceService.createApp(
+            name: event.name,
+            desc: event.desc ?? "",
+          );
+          result.fold(
+            (app) => {},
+            (error) {
+              Log.error(error);
+              emit(state.copyWith(successOrFailure: right(error)));
+            },
+          );
         },
         didReceiveApps: (e) async {
           emit(e.appsOrFail.fold(
-            (apps) => state.copyWith(apps: apps, successOrFailure: left(unit)),
+            (views) =>
+                state.copyWith(views: views, successOrFailure: left(unit)),
             (err) => state.copyWith(successOrFailure: right(err)),
           ));
         },
         moveApp: (_MoveApp value) {
-          if (state.apps.length > value.fromIndex) {
-            final app = state.apps[value.fromIndex];
+          if (state.views.length > value.fromIndex) {
+            final view = state.views[value.fromIndex];
             _workspaceService.moveApp(
-                appId: app.id,
+                appId: view.id,
                 fromIndex: value.fromIndex,
                 toIndex: value.toIndex);
-            final apps = List<AppPB>.from(state.apps);
+            final apps = List<ViewPB>.from(state.views);
             apps.insert(value.toIndex, apps.removeAt(value.fromIndex));
-            emit(state.copyWith(apps: apps));
+            emit(state.copyWith(views: apps));
           }
         },
       );
@@ -68,24 +79,11 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
     return super.close();
   }
 
-  Future<void> _performActionOnCreateApp(
-      _CreateApp event, Emitter<MenuState> emit) async {
-    final result = await _workspaceService.createApp(
-        name: event.name, desc: event.desc ?? "");
-    result.fold(
-      (app) => {},
-      (error) {
-        Log.error(error);
-        emit(state.copyWith(successOrFailure: right(error)));
-      },
-    );
-  }
-
   // ignore: unused_element
   Future<void> _fetchApps(Emitter<MenuState> emit) async {
     final appsOrFail = await _workspaceService.getApps();
     emit(appsOrFail.fold(
-      (apps) => state.copyWith(apps: apps),
+      (views) => state.copyWith(views: views),
       (error) {
         Log.error(error);
         return state.copyWith(successOrFailure: right(error));
@@ -93,7 +91,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
     ));
   }
 
-  void _handleAppsOrFail(Either<List<AppPB>, FlowyError> appsOrFail) {
+  void _handleAppsOrFail(Either<List<ViewPB>, FlowyError> appsOrFail) {
     appsOrFail.fold(
       (apps) => add(MenuEvent.didReceiveApps(left(apps))),
       (error) => add(MenuEvent.didReceiveApps(right(error))),
@@ -108,19 +106,19 @@ class MenuEvent with _$MenuEvent {
   const factory MenuEvent.createApp(String name, {String? desc}) = _CreateApp;
   const factory MenuEvent.moveApp(int fromIndex, int toIndex) = _MoveApp;
   const factory MenuEvent.didReceiveApps(
-      Either<List<AppPB>, FlowyError> appsOrFail) = _ReceiveApps;
+      Either<List<ViewPB>, FlowyError> appsOrFail) = _ReceiveApps;
 }
 
 @freezed
 class MenuState with _$MenuState {
   const factory MenuState({
-    required List<AppPB> apps,
+    required List<ViewPB> views,
     required Either<Unit, FlowyError> successOrFailure,
     required Plugin plugin,
   }) = _MenuState;
 
   factory MenuState.initial(WorkspacePB workspace) => MenuState(
-        apps: workspace.apps.items,
+        views: workspace.views,
         successOrFailure: left(unit),
         plugin: makePlugin(pluginType: PluginType.blank),
       );

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:appflowy/user/application/user_listener.dart';
 import 'package:appflowy/user/application/user_service.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart

@@ -3,7 +3,7 @@ import 'dart:async';
 import 'package:appflowy/workspace/application/app/app_bloc.dart';
 import 'package:appflowy/workspace/application/app/app_service.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 12 - 12
frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart

@@ -1,26 +1,26 @@
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 class SettingsFileExportState {
   SettingsFileExportState({
-    required this.apps,
+    required this.views,
   }) {
     initialize();
   }
 
-  List<AppPB> apps;
+  List<ViewPB> views;
   List<bool> expanded = [];
   List<bool> selectedApps = [];
   List<List<bool>> selectedItems = [];
 
   SettingsFileExportState copyWith({
-    List<AppPB>? apps,
+    List<ViewPB>? views,
     List<bool>? expanded,
     List<bool>? selectedApps,
     List<List<bool>>? selectedItems,
   }) {
     final state = SettingsFileExportState(
-      apps: apps ?? this.apps,
+      views: views ?? this.views,
     );
     state.expanded = expanded ?? this.expanded;
     state.selectedApps = selectedApps ?? this.selectedApps;
@@ -29,17 +29,17 @@ class SettingsFileExportState {
   }
 
   void initialize() {
-    expanded = apps.map((e) => true).toList();
-    selectedApps = apps.map((e) => true).toList();
+    expanded = views.map((e) => true).toList();
+    selectedApps = views.map((e) => true).toList();
     selectedItems =
-        apps.map((e) => e.belongings.items.map((e) => true).toList()).toList();
+        views.map((e) => e.belongings.map((e) => true).toList()).toList();
   }
 }
 
 class SettingsFileExporterCubit extends Cubit<SettingsFileExportState> {
   SettingsFileExporterCubit({
-    required List<AppPB> apps,
-  }) : super(SettingsFileExportState(apps: apps));
+    required List<ViewPB> views,
+  }) : super(SettingsFileExportState(views: views));
 
   void selectOrDeselectItem(int outerIndex, int innerIndex) {
     final selectedItems = state.selectedItems;
@@ -55,7 +55,7 @@ class SettingsFileExporterCubit extends Cubit<SettingsFileExportState> {
   }
 
   Map<String, List<String>> fetchSelectedPages() {
-    final apps = state.apps;
+    final apps = state.views;
     final selectedItems = state.selectedItems;
     Map<String, List<String>> result = {};
     for (var i = 0; i < selectedItems.length; i++) {
@@ -63,7 +63,7 @@ class SettingsFileExporterCubit extends Cubit<SettingsFileExportState> {
       final ids = <String>[];
       for (var j = 0; j < selectedItem.length; j++) {
         if (selectedItem[j]) {
-          ids.add(apps[i].belongings.items[j].id);
+          ids.add(apps[i].belongings[j].id);
         }
       }
       if (ids.isNotEmpty) {

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:appflowy/workspace/application/view/view_listener.dart';
 import 'package:appflowy/workspace/application/view/view_service.dart';
 import 'package:dartz/dartz.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart

@@ -1,6 +1,6 @@
 import 'package:appflowy/startup/plugin/plugin.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 
 enum FlowyPlugin {

+ 2 - 2
frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart

@@ -3,9 +3,9 @@ import 'dart:typed_data';
 import 'package:appflowy/core/folder_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart';
 import 'package:appflowy_backend/rust_stream.dart';
 import 'package:flowy_infra/notifier.dart';
 

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart

@@ -1,7 +1,7 @@
 import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 
 class ViewService {

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/application/workspace/welcome_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:appflowy/user/application/user_listener.dart';
 import 'package:appflowy/user/application/user_service.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 6 - 6
frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart

@@ -1,16 +1,16 @@
 import 'dart:async';
 import 'dart:typed_data';
 import 'package:appflowy/core/folder_notification.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
     show UserProfilePB;
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart';
 
-typedef AppListNotifyValue = Either<List<AppPB>, FlowyError>;
+typedef AppListNotifyValue = Either<List<ViewPB>, FlowyError>;
 typedef WorkspaceNotifyValue = Either<WorkspacePB, FlowyError>;
 
 class WorkspaceListener {
@@ -55,10 +55,10 @@ class WorkspaceListener {
           (error) => _workspaceUpdatedNotifier?.value = right(error),
         );
         break;
-      case FolderNotification.DidUpdateWorkspaceApps:
+      case FolderNotification.DidUpdateWorkspaceViews:
         result.fold(
           (payload) => _appsChangedNotifier?.value =
-              left(RepeatedAppPB.fromBuffer(payload).items),
+              left(RepeatedViewPB.fromBuffer(payload).items),
           (error) => _appsChangedNotifier?.value = right(error),
         );
         break;

+ 16 - 10
frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart

@@ -4,10 +4,14 @@ import 'package:dartz/dartz.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'
-    show MoveFolderItemPayloadPB, MoveFolderItemType;
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'
+    show
+        CreateViewPayloadPB,
+        MoveFolderItemPayloadPB,
+        MoveFolderItemType,
+        ViewLayoutTypePB,
+        ViewPB;
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 
 import 'package:appflowy/generated/locale_keys.g.dart';
 
@@ -16,13 +20,15 @@ class WorkspaceService {
   WorkspaceService({
     required this.workspaceId,
   });
-  Future<Either<AppPB, FlowyError>> createApp(
+  Future<Either<ViewPB, FlowyError>> createApp(
       {required String name, String? desc}) {
-    final payload = CreateAppPayloadPB.create()
+    final payload = CreateViewPayloadPB.create()
+      ..belongToId = workspaceId
       ..name = name
-      ..workspaceId = workspaceId
-      ..desc = desc ?? "";
-    return FolderEventCreateApp(payload).send();
+      ..desc = desc ?? ""
+      ..layout = ViewLayoutTypePB.Document;
+
+    return FolderEventCreateView(payload).send();
   }
 
   Future<Either<WorkspacePB, FlowyError>> getWorkspace() {
@@ -44,7 +50,7 @@ class WorkspaceService {
     });
   }
 
-  Future<Either<List<AppPB>, FlowyError>> getApps() {
+  Future<Either<List<ViewPB>, FlowyError>> getApps() {
     final payload = WorkspaceIdPB.create()..value = workspaceId;
     return FolderEventReadWorkspaceApps(payload).send().then((result) {
       return result.fold(

+ 3 - 3
frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart

@@ -10,7 +10,7 @@ import 'package:appflowy/workspace/presentation/home/hotkeys.dart';
 import 'package:appflowy/workspace/presentation/widgets/edit_panel/panel_animation.dart';
 import 'package:appflowy/workspace/presentation/widgets/float_bubble/question_bubble.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
     show UserProfilePB;
 import 'package:flowy_infra_ui/style_widget/container.dart';
@@ -263,8 +263,8 @@ class HomeScreenStackAdaptor extends HomeStackDelegate {
     final homeService = HomeService();
     homeService.readApp(appId: view.appId).then((result) {
       result.fold(
-        (appPB) {
-          final List<ViewPB> views = appPB.belongings.items;
+        (parentView) {
+          final List<ViewPB> views = parentView.belongings;
           if (views.isNotEmpty) {
             var lastView = views.last;
             if (index != null && index != 0 && views.length > index - 1) {

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart

@@ -5,7 +5,7 @@ import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
 import 'package:appflowy/workspace/presentation/home/navigation.dart';
 import 'package:appflowy/workspace/presentation/home/toast.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flowy_infra_ui/style_widget/extension.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';

+ 5 - 5
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart

@@ -2,12 +2,12 @@ import 'dart:convert';
 
 import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
 import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:expandable/expandable.dart';
 import 'package:flowy_infra/icon_data.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:appflowy/workspace/application/app/app_bloc.dart';
@@ -19,7 +19,7 @@ import '../menu_app.dart';
 import 'add_button.dart';
 
 class MenuAppHeader extends StatelessWidget {
-  final AppPB app;
+  final ViewPB app;
   const MenuAppHeader(
     this.app, {
     Key? key,
@@ -83,7 +83,7 @@ class MenuAppHeader extends StatelessWidget {
             case AppDisclosureAction.rename:
               NavigatorTextFieldDialog(
                 title: LocaleKeys.menuAppHeader_renameDialog.tr(),
-                value: context.read<AppBloc>().state.app.name,
+                value: context.read<AppBloc>().state.view.name,
                 confirm: (newValue) {
                   context.read<AppBloc>().add(AppEvent.rename(newValue));
                 },
@@ -166,8 +166,8 @@ class AppActionList extends StatelessWidget {
           onSecondaryTap: () {
             controller.show();
           },
-          child: BlocSelector<AppBloc, AppState, AppPB>(
-            selector: (state) => state.app,
+          child: BlocSelector<AppBloc, AppState, ViewPB>(
+            selector: (state) => state.view,
             builder: (context, app) => FlowyText.medium(
               app.name,
               overflow: TextOverflow.ellipsis,

+ 6 - 6
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/menu_app.dart

@@ -1,6 +1,6 @@
 import 'package:appflowy/workspace/presentation/home/menu/menu.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:expandable/expandable.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:appflowy/startup/startup.dart';
@@ -9,8 +9,8 @@ import 'package:provider/provider.dart';
 import 'section/section.dart';
 
 class MenuApp extends StatefulWidget {
-  final AppPB app;
-  const MenuApp(this.app, {Key? key}) : super(key: key);
+  final ViewPB view;
+  const MenuApp(this.view, {Key? key}) : super(key: key);
 
   @override
   State<MenuApp> createState() => _MenuAppState();
@@ -21,7 +21,7 @@ class _MenuAppState extends State<MenuApp> {
 
   @override
   void initState() {
-    viewDataContext = AppViewDataContext(appId: widget.app.id);
+    viewDataContext = AppViewDataContext(viewId: widget.view.id);
     super.initState();
   }
 
@@ -31,7 +31,7 @@ class _MenuAppState extends State<MenuApp> {
       providers: [
         BlocProvider<AppBloc>(
           create: (context) {
-            final appBloc = getIt<AppBloc>(param1: widget.app);
+            final appBloc = AppBloc(view: widget.view);
             appBloc.add(const AppEvent.initial());
             return appBloc;
           },
@@ -86,7 +86,7 @@ class _MenuAppState extends State<MenuApp> {
                 iconPadding: EdgeInsets.zero,
                 hasIcon: false,
               ),
-              header: MenuAppHeader(widget.app),
+              header: MenuAppHeader(widget.view),
               expanded: ViewSection(appViewData: viewDataContext),
               collapsed: const SizedBox(),
             ),

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/section/item.dart

@@ -7,7 +7,7 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';

+ 3 - 3
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu.dart

@@ -8,8 +8,8 @@ import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
 import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
 import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
 import 'package:appflowy/workspace/presentation/home/home_stack.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.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/protobuf.dart'
     show UserProfilePB;
 import 'package:easy_localization/easy_localization.dart';
@@ -112,7 +112,7 @@ class HomeMenu extends StatelessWidget {
         child: ScrollConfiguration(
           behavior: const ScrollBehavior().copyWith(scrollbars: false),
           child: BlocSelector<MenuBloc, MenuState, List<Widget>>(
-            selector: (state) => state.apps
+            selector: (state) => state.views
                 .map((app) => MenuApp(app, key: ValueKey(app.id)))
                 .toList(),
             builder: (context, menuItems) {

+ 6 - 6
frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart

@@ -6,7 +6,7 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
@@ -73,9 +73,9 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
             snapshot.connectionState == ConnectionState.done) {
           final workspaces = snapshot.data?.getLeftOrNull<WorkspaceSettingPB>();
           if (workspaces != null) {
-            final apps = workspaces.workspace.apps.items;
+            final views = workspaces.workspace.views;
             return BlocProvider<SettingsFileExporterCubit>(
-              create: (_) => SettingsFileExporterCubit(apps: apps),
+              create: (_) => SettingsFileExporterCubit(views: views),
               child: const _ExpandedList(),
             );
           }
@@ -118,7 +118,7 @@ class _ExpandedListState extends State<_ExpandedList> {
   }
 
   List<Widget> _buildChildren(BuildContext context) {
-    final apps = context.read<SettingsFileExporterCubit>().state.apps;
+    final apps = context.read<SettingsFileExporterCubit>().state.views;
     List<Widget> children = [];
     for (var i = 0; i < apps.length; i++) {
       children.add(_buildExpandedItem(context, i));
@@ -128,14 +128,14 @@ class _ExpandedListState extends State<_ExpandedList> {
 
   Widget _buildExpandedItem(BuildContext context, int index) {
     final state = context.read<SettingsFileExporterCubit>().state;
-    final apps = state.apps;
+    final apps = state.views;
     final expanded = state.expanded;
     final selectedItems = state.selectedItems;
     final isExpaned = expanded[index] == true;
     List<Widget> expandedChildren = [];
     if (isExpaned) {
       for (var i = 0; i < selectedItems[index].length; i++) {
-        final name = apps[index].belongings.items[i].name;
+        final name = apps[index].belongings[i].name;
         final checkbox = CheckboxListTile(
           value: selectedItems[index][i],
           onChanged: (value) {

+ 1 - 1
frontend/appflowy_flutter/lib/workspace/presentation/widgets/left_bar_item.dart

@@ -1,7 +1,7 @@
 import 'package:appflowy/workspace/application/view/view_listener.dart';
 import 'package:appflowy/workspace/application/view/view_service.dart';
 import 'package:appflowy_backend/log.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter/material.dart';
 
 class ViewLeftBarItem extends StatefulWidget {

+ 2 - 2
frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart

@@ -15,7 +15,7 @@ import 'dart:typed_data';
 import 'package:appflowy_backend/ffi.dart' as ffi;
 import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
 import 'package:appflowy_backend/protobuf/dart-ffi/protobuf.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
 
@@ -25,7 +25,7 @@ import 'dart:convert' show utf8;
 import '../protobuf/flowy-net/event_map.pb.dart';
 import 'error.dart';
 
-part 'dart_event/flowy-folder/dart_event.dart';
+part 'dart_event/flowy-folder2/dart_event.dart';
 part 'dart_event/flowy-net/dart_event.dart';
 part 'dart_event/flowy-user/dart_event.dart';
 part 'dart_event/flowy-database/dart_event.dart';

+ 1 - 1
frontend/appflowy_flutter/test/bloc_test/board_test/util.dart

@@ -11,7 +11,7 @@ import 'package:appflowy/plugins/database_view/application/database_controller.d
 import 'package:appflowy/plugins/database_view/grid/application/row/row_bloc.dart';
 import 'package:appflowy/workspace/application/app/app_service.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pbenum.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 
 import '../../util.dart';

+ 1 - 1
frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart

@@ -13,7 +13,7 @@ import 'package:appflowy/workspace/application/app/app_service.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pbenum.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
 import 'package:dartz/dartz.dart';
 

+ 10 - 10
frontend/appflowy_flutter/test/bloc_test/home_test/app_bloc_test.dart

@@ -15,30 +15,30 @@ void main() {
 
   test('rename app test', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(const AppEvent.rename('Hello world'));
     await blocResponseFuture();
 
-    assert(bloc.state.app.name == 'Hello world');
+    expect(bloc.state.view.name, 'Hello world');
   });
 
   test('delete app test', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(const AppEvent.delete());
     await blocResponseFuture();
 
     final apps = await testContext.loadApps();
-    assert(apps.where((element) => element.id == app.id).isEmpty);
+    expect(apps.where((element) => element.id == app.id).isEmpty, true);
   });
 
   test('create documents in order', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("1", DocumentPluginBuilder()));
@@ -55,7 +55,7 @@ void main() {
 
   test('reorder documents test', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("1", DocumentPluginBuilder()));
@@ -66,7 +66,7 @@ void main() {
     await blocResponseFuture();
     assert(bloc.state.views.length == 3);
 
-    final appViewData = AppViewDataContext(appId: app.id);
+    final appViewData = AppViewDataContext(viewId: app.id);
     appViewData.views = bloc.state.views;
 
     final viewSectionBloc = ViewSectionBloc(
@@ -84,7 +84,7 @@ void main() {
 
   test('open latest view test', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
     assert(
       bloc.state.latestCreatedView == null,
@@ -108,7 +108,7 @@ void main() {
 
   test('open latest documents test', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("document 1", DocumentPluginBuilder()));
@@ -135,7 +135,7 @@ void main() {
 
   test('open latest document test', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("document 1", DocumentPluginBuilder()));

+ 5 - 5
frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart

@@ -3,7 +3,7 @@ import 'package:appflowy/plugins/database_view/board/board.dart';
 import 'package:appflowy/plugins/database_view/grid/grid.dart';
 import 'package:appflowy/plugins/document/document.dart';
 import 'package:appflowy/workspace/application/app/app_bloc.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter_test/flutter_test.dart';
 import '../../util.dart';
 
@@ -15,7 +15,7 @@ void main() {
 
   test('create a document', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("Test document", DocumentPluginBuilder()));
@@ -28,7 +28,7 @@ void main() {
 
   test('create a grid', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("Test grid", GridPluginBuilder()));
@@ -41,7 +41,7 @@ void main() {
 
   test('create a kanban', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("Test board", BoardPluginBuilder()));
@@ -54,7 +54,7 @@ void main() {
 
   test('create a calendar', () async {
     final app = await testContext.createTestApp();
-    final bloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final bloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     bloc.add(AppEvent.createView("Test calendar", CalendarPluginBuilder()));

+ 1 - 1
frontend/appflowy_flutter/test/bloc_test/home_test/home_bloc_test.dart

@@ -37,7 +37,7 @@ void main() {
     await blocResponseFuture();
 
     final app = await testContext.createTestApp();
-    final appBloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final appBloc = AppBloc(view: app)..add(const AppEvent.initial());
     assert(appBloc.state.latestCreatedView == null);
 
     appBloc.add(AppEvent.createView("New document", DocumentPluginBuilder()));

+ 4 - 4
frontend/appflowy_flutter/test/bloc_test/home_test/menu_bloc_test.dart

@@ -16,7 +16,7 @@ void main() {
     )..add(const MenuEvent.initial());
     await blocResponseFuture();
 
-    assert(menuBloc.state.apps.length == 1);
+    assert(menuBloc.state.views.length == 1);
   });
 
   test('reorder apps', () async {
@@ -35,8 +35,8 @@ void main() {
     menuBloc.add(const MenuEvent.moveApp(1, 3));
     await blocResponseFuture();
 
-    assert(menuBloc.state.apps[1].name == 'App 2');
-    assert(menuBloc.state.apps[2].name == 'App 3');
-    assert(menuBloc.state.apps[3].name == 'App 1');
+    assert(menuBloc.state.views[1].name == 'App 2');
+    assert(menuBloc.state.views[2].name == 'App 3');
+    assert(menuBloc.state.views[3].name == 'App 1');
   });
 }

+ 8 - 9
frontend/appflowy_flutter/test/bloc_test/home_test/trash_bloc_test.dart

@@ -1,14 +1,13 @@
 import 'package:appflowy/plugins/document/document.dart';
 import 'package:appflowy/plugins/trash/application/trash_bloc.dart';
 import 'package:appflowy/workspace/application/app/app_bloc.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import '../../util.dart';
 
 class TrashTestContext {
-  late AppPB app;
+  late ViewPB view;
   late AppBloc appBloc;
   late List<ViewPB> allViews;
   final AppFlowyUnitTest unitTest;
@@ -16,8 +15,8 @@ class TrashTestContext {
   TrashTestContext(this.unitTest);
 
   Future<void> initialize() async {
-    app = await unitTest.createTestApp();
-    appBloc = AppBloc(app: app)..add(const AppEvent.initial());
+    view = await unitTest.createTestApp();
+    appBloc = AppBloc(view: view)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     appBloc.add(AppEvent.createView(
@@ -40,7 +39,7 @@ class TrashTestContext {
     );
     await blocResponseFuture();
 
-    allViews = [...appBloc.state.app.belongings.items];
+    allViews = [...appBloc.state.view.belongings];
     assert(allViews.length == 3, 'but receive ${allViews.length}');
   }
 }
@@ -65,17 +64,17 @@ void main() {
       await blocResponseFuture(millisecond: 200);
 
       // delete a view
-      final deletedView = context.appBloc.state.app.belongings.items[0];
+      final deletedView = context.appBloc.state.view.belongings[0];
       context.appBloc.add(AppEvent.deleteView(deletedView.id));
       await blocResponseFuture();
-      assert(context.appBloc.state.app.belongings.items.length == 2);
+      assert(context.appBloc.state.view.belongings.length == 2);
       assert(trashBloc.state.objects.length == 1);
       assert(trashBloc.state.objects.first.id == deletedView.id);
 
       // put back
       trashBloc.add(TrashEvent.putback(deletedView.id));
       await blocResponseFuture();
-      assert(context.appBloc.state.app.belongings.items.length == 3);
+      assert(context.appBloc.state.view.belongings.length == 3);
       assert(trashBloc.state.objects.isEmpty);
 
       // delete all views

+ 3 - 3
frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart

@@ -13,7 +13,7 @@ void main() {
 
   test('rename view test', () async {
     final app = await testContext.createTestApp();
-    final appBloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final appBloc = AppBloc(view: app)..add(const AppEvent.initial());
     appBloc.add(AppEvent.createView(
       "Test document",
       DocumentPluginBuilder(),
@@ -30,7 +30,7 @@ void main() {
 
   test('duplicate view test', () async {
     final app = await testContext.createTestApp();
-    final appBloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final appBloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     appBloc.add(AppEvent.createView(
@@ -51,7 +51,7 @@ void main() {
 
   test('delete view test', () async {
     final app = await testContext.createTestApp();
-    final appBloc = AppBloc(app: app)..add(const AppEvent.initial());
+    final appBloc = AppBloc(view: app)..add(const AppEvent.initial());
     await blocResponseFuture();
 
     appBloc.add(AppEvent.createView(

+ 4 - 4
frontend/appflowy_flutter/test/util.dart

@@ -3,10 +3,10 @@ import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/user/application/auth_service.dart';
 import 'package:appflowy/user/application/user_service.dart';
 import 'package:appflowy/workspace/application/workspace/workspace_service.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/uuid.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
@@ -81,7 +81,7 @@ class AppFlowyUnitTest {
     workspaceService = WorkspaceService(workspaceId: currentWorkspace.id);
   }
 
-  Future<AppPB> createTestApp() async {
+  Future<ViewPB> createTestApp() async {
     final result = await workspaceService.createApp(name: "Test App");
     return result.fold(
       (app) => app,
@@ -89,7 +89,7 @@ class AppFlowyUnitTest {
     );
   }
 
-  Future<List<AppPB>> loadApps() async {
+  Future<List<ViewPB>> loadApps() async {
     final result = await workspaceService.getApps();
 
     return result.fold(

+ 285 - 82
frontend/appflowy_tauri/src-tauri/Cargo.lock

@@ -72,9 +72,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.68"
+version = "1.0.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
+checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
 
 [[package]]
 name = "appflowy_tauri"
@@ -123,7 +123,7 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -134,7 +134,7 @@ checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -274,7 +274,7 @@ dependencies = [
  "borsh-schema-derive-internal",
  "proc-macro-crate 0.1.5",
  "proc-macro2",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -285,7 +285,7 @@ checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -296,7 +296,7 @@ checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -354,7 +354,7 @@ checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -460,9 +460,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.23"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
  "iana-time-zone",
  "js-sys",
@@ -517,7 +517,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -561,6 +561,70 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "collab"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "anyhow",
+ "bytes",
+ "collab-persistence",
+ "lib0",
+ "parking_lot 0.12.1",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "tracing",
+ "y-sync",
+ "yrs",
+]
+
+[[package]]
+name = "collab-derive"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_json",
+ "syn 1.0.109",
+ "yrs",
+]
+
+[[package]]
+name = "collab-folder"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "anyhow",
+ "collab",
+ "collab-derive",
+ "collab-persistence",
+ "parking_lot 0.12.1",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "collab-persistence"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "bincode",
+ "chrono",
+ "lib0",
+ "serde",
+ "sled",
+ "smallvec",
+ "thiserror",
+ "tokio",
+ "yrs",
+]
+
 [[package]]
 name = "color_quant"
 version = "1.1.0"
@@ -736,7 +800,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "smallvec",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -746,7 +810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
 dependencies = [
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -756,7 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
 dependencies = [
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -789,7 +853,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "scratch",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -806,7 +870,7 @@ checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -830,7 +894,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -841,7 +905,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
 dependencies = [
  "darling_core",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -854,7 +918,7 @@ dependencies = [
  "hashbrown",
  "lock_api",
  "once_cell",
- "parking_lot_core",
+ "parking_lot_core 0.9.6",
 ]
 
 [[package]]
@@ -877,7 +941,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -890,7 +954,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustc_version 0.4.0",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -918,7 +982,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1133,7 +1197,7 @@ version = "0.1.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1160,7 +1224,7 @@ dependencies = [
  "folder-model",
  "lib-infra",
  "lib-ot",
- "parking_lot",
+ "parking_lot 0.12.1",
  "revision-model",
  "serde",
  "serde_json",
@@ -1178,7 +1242,7 @@ dependencies = [
  "futures-util",
  "lib-infra",
  "lib-ws",
- "parking_lot",
+ "parking_lot 0.12.1",
  "serde",
  "serde_repr",
  "thiserror",
@@ -1204,7 +1268,7 @@ dependencies = [
  "serde",
  "serde_json",
  "similar",
- "syn",
+ "syn 1.0.109",
  "tera",
  "toml",
  "walkdir",
@@ -1215,12 +1279,14 @@ name = "flowy-core"
 version = "0.1.0"
 dependencies = [
  "bytes",
+ "collab-persistence",
  "database-model",
  "flowy-client-ws",
  "flowy-database",
  "flowy-document",
  "flowy-error",
  "flowy-folder",
+ "flowy-folder2",
  "flowy-net",
  "flowy-revision",
  "flowy-sqlite",
@@ -1231,7 +1297,7 @@ dependencies = [
  "lib-infra",
  "lib-log",
  "lib-ws",
- "parking_lot",
+ "parking_lot 0.12.1",
  "revision-model",
  "serde",
  "serde_json",
@@ -1271,7 +1337,7 @@ dependencies = [
  "lib-infra",
  "lib-ot",
  "nanoid",
- "parking_lot",
+ "parking_lot 0.12.1",
  "protobuf",
  "rayon",
  "regex",
@@ -1299,7 +1365,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde_json",
- "syn",
+ "syn 1.0.109",
  "walkdir",
 ]
 
@@ -1388,7 +1454,7 @@ dependencies = [
  "lib-infra",
  "lib-ot",
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "pin-project",
  "protobuf",
  "revision-model",
@@ -1402,6 +1468,33 @@ dependencies = [
  "ws-model",
 ]
 
+[[package]]
+name = "flowy-folder2"
+version = "0.1.0"
+dependencies = [
+ "bytes",
+ "chrono",
+ "collab",
+ "collab-folder",
+ "collab-persistence",
+ "flowy-codegen",
+ "flowy-derive",
+ "flowy-document",
+ "flowy-error",
+ "flowy-notification",
+ "lazy_static",
+ "lib-dispatch",
+ "lib-infra",
+ "nanoid",
+ "parking_lot 0.12.1",
+ "protobuf",
+ "strum",
+ "strum_macros",
+ "tokio",
+ "tracing",
+ "unicode-segmentation",
+]
+
 [[package]]
 name = "flowy-net"
 version = "0.1.0"
@@ -1419,7 +1512,7 @@ dependencies = [
  "flowy-derive",
  "flowy-document",
  "flowy-error",
- "flowy-folder",
+ "flowy-folder2",
  "flowy-server-sync",
  "flowy-sync",
  "flowy-user",
@@ -1431,7 +1524,7 @@ dependencies = [
  "lib-infra",
  "lib-ws",
  "nanoid",
- "parking_lot",
+ "parking_lot 0.12.1",
  "protobuf",
  "reqwest",
  "revision-model",
@@ -1536,7 +1629,7 @@ dependencies = [
  "folder-model",
  "lib-infra",
  "lib-ot",
- "parking_lot",
+ "parking_lot 0.12.1",
  "revision-model",
  "serde",
  "strum",
@@ -1562,6 +1655,7 @@ name = "flowy-user"
 version = "0.1.0"
 dependencies = [
  "bytes",
+ "collab-persistence",
  "diesel",
  "diesel_derives",
  "flowy-codegen",
@@ -1574,7 +1668,7 @@ dependencies = [
  "lib-infra",
  "log",
  "once_cell",
- "parking_lot",
+ "parking_lot 0.12.1",
  "protobuf",
  "serde",
  "serde_json",
@@ -1625,6 +1719,16 @@ dependencies = [
  "percent-encoding",
 ]
 
+[[package]]
+name = "fs2"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 name = "futf"
 version = "0.1.5"
@@ -1691,7 +1795,7 @@ checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1845,8 +1949,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
 dependencies = [
  "cfg-if",
+ "js-sys",
  "libc",
  "wasi 0.9.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
 ]
 
 [[package]]
@@ -1928,7 +2034,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2034,7 +2140,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2100,7 +2206,7 @@ dependencies = [
  "markup5ever",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2527,7 +2633,7 @@ dependencies = [
  "futures-util",
  "lib-infra",
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "pin-project",
  "protobuf",
  "serde",
@@ -2540,6 +2646,17 @@ dependencies = [
  "url",
 ]
 
+[[package]]
+name = "lib0"
+version = "0.16.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daf23122cb1c970b77ea6030eac5e328669415b65d2ab245c99bfb110f9d62dc"
+dependencies = [
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
 [[package]]
 name = "libc"
 version = "0.2.139"
@@ -2716,7 +2833,7 @@ dependencies = [
  "migrations_internals",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2892,7 +3009,7 @@ dependencies = [
  "proc-macro-crate 1.2.1",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2977,7 +3094,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3040,6 +3157,17 @@ dependencies = [
  "system-deps 6.0.3",
 ]
 
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core 0.8.6",
+]
+
 [[package]]
 name = "parking_lot"
 version = "0.12.1"
@@ -3047,7 +3175,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core",
+ "parking_lot_core 0.9.6",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec",
+ "winapi",
 ]
 
 [[package]]
@@ -3120,7 +3262,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3226,7 +3368,7 @@ dependencies = [
  "proc-macro-hack",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3240,7 +3382,7 @@ dependencies = [
  "proc-macro-hack",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3288,7 +3430,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3376,7 +3518,7 @@ dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "version_check",
 ]
 
@@ -3399,9 +3541,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.51"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
@@ -3510,14 +3652,14 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -3529,7 +3671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
 dependencies = [
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "scheduled-thread-pool",
 ]
 
@@ -3784,7 +3926,7 @@ checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3891,7 +4033,7 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf"
 dependencies = [
- "parking_lot",
+ "parking_lot 0.12.1",
 ]
 
 [[package]]
@@ -3990,9 +4132,9 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.152"
+version = "1.0.159"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
 dependencies = [
  "serde_derive",
 ]
@@ -4010,20 +4152,20 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.159"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.13",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
 dependencies = [
  "itoa 1.0.5",
  "ryu",
@@ -4038,7 +4180,7 @@ checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4072,7 +4214,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4094,7 +4236,7 @@ checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4170,6 +4312,22 @@ dependencies = [
  "autocfg",
 ]
 
+[[package]]
+name = "sled"
+version = "0.34.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
+dependencies = [
+ "crc32fast",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "fs2",
+ "fxhash",
+ "libc",
+ "log",
+ "parking_lot 0.11.2",
+]
+
 [[package]]
 name = "slug"
 version = "0.1.4"
@@ -4179,6 +4337,15 @@ dependencies = [
  "deunicode",
 ]
 
+[[package]]
+name = "smallstr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f"
+dependencies = [
+ "smallvec",
+]
+
 [[package]]
 name = "smallvec"
 version = "1.10.0"
@@ -4252,7 +4419,7 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
 dependencies = [
  "new_debug_unreachable",
  "once_cell",
- "parking_lot",
+ "parking_lot 0.12.1",
  "phf_shared 0.10.0",
  "precomputed-hash",
  "serde",
@@ -4291,7 +4458,7 @@ dependencies = [
  "heck 0.3.3",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4305,6 +4472,17 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "syn"
+version = "2.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "system-deps"
 version = "5.0.0"
@@ -4364,7 +4542,7 @@ dependencies = [
  "ndk-sys",
  "objc",
  "once_cell",
- "parking_lot",
+ "parking_lot 0.12.1",
  "paste",
  "png",
  "raw-window-handle",
@@ -4486,7 +4664,7 @@ dependencies = [
  "heck 0.4.0",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "tauri-codegen",
  "tauri-utils",
 ]
@@ -4633,22 +4811,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.13",
 ]
 
 [[package]]
@@ -4736,7 +4914,7 @@ dependencies = [
  "memchr",
  "mio",
  "num_cpus",
- "parking_lot",
+ "parking_lot 0.12.1",
  "pin-project-lite",
  "signal-hook-registry",
  "socket2",
@@ -4752,7 +4930,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4839,7 +5017,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -5220,7 +5398,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "wasm-bindgen-shared",
 ]
 
@@ -5254,7 +5432,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -5342,7 +5520,7 @@ checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -5432,7 +5610,7 @@ version = "0.39.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7"
 dependencies = [
- "syn",
+ "syn 1.0.109",
  "windows-tokens",
 ]
 
@@ -5662,6 +5840,17 @@ version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
 
+[[package]]
+name = "y-sync"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e77a143afe4dde83bc987ad3119228d0f107053a3da131a00738cb2d7f496641"
+dependencies = [
+ "lib0",
+ "thiserror",
+ "yrs",
+]
+
 [[package]]
 name = "yaml-rust"
 version = "0.4.5"
@@ -5670,3 +5859,17 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
 dependencies = [
  "linked-hash-map",
 ]
+
+[[package]]
+name = "yrs"
+version = "0.16.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c2aef2bf89b4f7c003f9c73f1c8097427ca32e1d006443f3f607f11e79a797b"
+dependencies = [
+ "atomic_refcell",
+ "lib0",
+ "rand 0.7.3",
+ "smallstr",
+ "smallvec",
+ "thiserror",
+]

+ 7 - 0
frontend/appflowy_tauri/src-tauri/Cargo.toml

@@ -31,3 +31,10 @@ default = ["custom-protocol"]
 # this feature is used used for production builds where `devPath` points to the filesystem
 # DO NOT remove this
 custom-protocol = ["tauri/custom-protocol"]
+
+[patch.crates-io]
+collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" }
+collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" }
+collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" }
+
+

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts

@@ -2,8 +2,8 @@ import { currentUserActions } from '../../stores/reducers/current-user/slice';
 import { useAppDispatch, useAppSelector } from '../../stores/store';
 import { UserProfilePB } from '../../../services/backend/events/flowy-user';
 import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
-import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder';
-import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder/workspace';
+import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
+import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace';
 import { Log } from '../../utils/log';
 
 export const useAuth = () => {

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts

@@ -39,8 +39,8 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
     void appObserver.subscribe({
       onAppChanged: (change) => {
         if (change.ok) {
-          const app: AppPB = change.val;
-          const updatedPages: IPage[] = app.belongings.items.map((view) => ({
+          const views = change.val;
+          const updatedPages: IPage[] = views.items.map((view) => ({
             id: view.id,
             folderId: view.app_id,
             pageType: view.layout,

+ 5 - 5
frontend/appflowy_tauri/src/appflowy_app/components/layout/Workspace.hooks.ts

@@ -6,11 +6,11 @@ import { UserBackendService } from '../../stores/effects/user/user_bd_svc';
 import { useError } from '../error/Error.hooks';
 
 export const useWorkspace = () => {
-  const appDispatch = useAppDispatch();
   const currentUser = useAppSelector((state) => state.currentUser);
-  const error = useError();
 
-  const userBackendService: UserBackendService = new UserBackendService(currentUser.id || '');
+  const appDispatch = useAppDispatch();
+  const error = useError();
+  const userBackendService: UserBackendService = new UserBackendService(currentUser.id || 0);
 
   const loadWorkspaceItems = async () => {
     try {
@@ -20,11 +20,11 @@ export const useWorkspace = () => {
       appDispatch(foldersActions.clearFolders());
       appDispatch(pagesActions.clearPages());
 
-      const apps = workspace.apps.items;
+      const apps = workspace.views;
       for (const app of apps) {
         appDispatch(foldersActions.addFolder({ id: app.id, title: app.name }));
 
-        const views = app.belongings.items;
+        const views = app.belongings;
         for (const view of views) {
           appDispatch(pagesActions.addPage({ folderId: app.id, id: view.id, pageType: view.layout, title: view.name }));
         }

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts

@@ -5,7 +5,7 @@ import {
   ViewPB,
   WorkspaceSettingPB,
 } from '../../../services/backend';
-import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder';
+import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
 import { AppBackendService } from '../../stores/effects/folder/app/app_bd_svc';
 import { DatabaseController } from '../../stores/effects/database/database_controller';
 import { RowInfo } from '../../stores/effects/database/row/row_cache';
@@ -31,7 +31,7 @@ import { SelectOptionBackendService } from '../../stores/effects/database/cell/s
 // Do not use it production code. Just for testing
 export async function createTestDatabaseView(layout: ViewLayoutTypePB): Promise<ViewPB> {
   const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap());
-  const app = workspaceSetting.workspace.apps.items[0];
+  const app = workspaceSetting.workspace.views[0];
   const appService = new AppBackendService(app.id);
   return await appService.createView({ name: 'New Grid', layoutType: layout });
 }

+ 4 - 4
frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts

@@ -1,10 +1,10 @@
-import { ViewLayoutTypePB, WorkspaceSettingPB } from '../../../services/backend';
-import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder';
-import { AppBackendService } from '../../stores/effects/folder/app/app_bd_svc';
+import { ViewLayoutTypePB, WorkspaceSettingPB } from '@/services/backend';
+import { FolderEventReadCurrentWorkspace } from '@/services/backend/events/flowy-folder2';
+import { AppBackendService } from '$app/stores/effects/folder/app/app_bd_svc';
 
 export async function createTestDocument() {
   const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap());
-  const app = workspaceSetting.workspace.apps.items[0];
+  const app = workspaceSetting.workspace.views[0];
   const appService = new AppBackendService(app.id);
   return await appService.createView({ name: 'New Document', layoutType: ViewLayoutTypePB.Document });
 }

+ 0 - 129
frontend/appflowy_tauri/src/appflowy_app/components/tests/TestApiButton.tsx

@@ -1,129 +0,0 @@
-import { SignInPayloadPB } from '../../../services/backend/models/flowy-user/index';
-import { nanoid } from 'nanoid';
-import { UserNotificationListener } from '../user/application/notifications';
-import {
-  ColorStylePB,
-  CreateAppPayloadPB,
-  CreateWorkspacePayloadPB,
-  FolderEventCreateApp,
-  FolderEventCreateWorkspace,
-  FolderEventOpenWorkspace,
-  WorkspaceIdPB,
-} from '../../../services/backend/events/flowy-folder';
-import { useEffect, useState } from 'react';
-import * as dependency_1 from '../../../services/backend/models/flowy-folder/app';
-import { UserEventGetUserSetting, UserEventSignIn } from '../../../services/backend/events/flowy-user';
-
-const TestApiButton = () => {
-  const [workspaceId, setWorkspaceId] = useState('');
-  const [appId, setAppId] = useState('');
-
-  useEffect(() => {
-    if (!workspaceId?.length) return;
-    void (async () => {
-      const openWorkspaceResult = await FolderEventOpenWorkspace(
-        WorkspaceIdPB.fromObject({
-          value: workspaceId,
-        })
-      );
-
-      if (openWorkspaceResult.ok) {
-        const pb = openWorkspaceResult.val;
-        console.log(pb.toObject());
-      } else {
-        throw new Error('open workspace error');
-      }
-
-      const createAppResult = await FolderEventCreateApp(
-        CreateAppPayloadPB.fromObject({
-          name: 'APP_1',
-          desc: 'Application One',
-          color_style: ColorStylePB.fromObject({ theme_color: 'light' }),
-          workspace_id: workspaceId,
-        })
-      );
-      if (createAppResult.ok) {
-        const pb = createAppResult.val;
-        const obj = pb.toObject();
-        console.log(obj);
-      } else {
-        throw new Error('create app error');
-      }
-    })();
-  }, [workspaceId]);
-
-  async function sendSignInEvent() {
-    const make_payload = () =>
-      SignInPayloadPB.fromObject({
-        email: nanoid(4) + '@gmail.com',
-        password: 'A!@123abc',
-        name: 'abc',
-      });
-
-    const listener = new UserNotificationListener({
-      onUserSignIn: (userProfile) => {
-        console.log(userProfile);
-      },
-      onProfileUpdate: (userProfile) => {
-        console.log(userProfile);
-        // stop listening the changes
-        void listener.stop();
-      },
-    });
-
-    await listener.start();
-
-    const signInResult = await UserEventSignIn(make_payload());
-    if (signInResult.ok) {
-      const pb = signInResult.val;
-      console.log(pb.toObject());
-    } else {
-      throw new Error('sign in error');
-    }
-
-    const getSettingsResult = await UserEventGetUserSetting();
-    if (getSettingsResult.ok) {
-      const pb = getSettingsResult.val;
-      console.log(pb.toObject());
-    } else {
-      throw new Error('get user settings error');
-    }
-
-    const createWorkspaceResult = await FolderEventCreateWorkspace(
-      CreateWorkspacePayloadPB.fromObject({
-        name: 'WS_1',
-        desc: 'Workspace One',
-      })
-    );
-
-    if (createWorkspaceResult.ok) {
-      const pb = createWorkspaceResult.val;
-      console.log(pb.toObject());
-      const workspace: {
-        id?: string;
-        name?: string;
-        desc?: string;
-        apps?: ReturnType<typeof dependency_1.RepeatedAppPB.prototype.toObject>;
-        modified_time?: number;
-        create_time?: number;
-      } = pb.toObject();
-      setWorkspaceId(workspace?.id || '');
-    } else {
-      throw new Error('create workspace error');
-    }
-
-    /**/
-  }
-
-  return (
-    <>
-      <div>
-        <button className='rounded-md bg-gray-300 p-4' type='button' onClick={() => sendSignInEvent()}>
-          Sign in and create sample data
-        </button>
-      </div>
-    </>
-  );
-};
-
-export default TestApiButton;

+ 1 - 1
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts

@@ -23,7 +23,7 @@ import {
   CreateRowPayloadPB,
   ViewIdPB,
 } from '@/services/backend';
-import { FolderEventCloseView } from '@/services/backend/events/flowy-folder';
+import { FolderEventCloseView } from '@/services/backend/events/flowy-folder2';
 
 /// A service that wraps the backend service
 export class DatabaseBackendService {

+ 1 - 1
frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_bd_svc.ts

@@ -8,7 +8,7 @@ import {
 } from '@/services/backend';
 import { DocumentEventApplyEdit, DocumentEventGetDocument } from '@/services/backend/events/flowy-document';
 import { Result } from 'ts-results';
-import { FolderEventCloseView } from '@/services/backend/events/flowy-folder';
+import { FolderEventCloseView } from '@/services/backend/events/flowy-folder2';
 
 export class DocumentBackendService {
   constructor(public readonly viewId: string) {}

+ 14 - 15
frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts

@@ -1,21 +1,20 @@
 import {
   FolderEventCreateView,
-  FolderEventDeleteApp,
   FolderEventDeleteView,
   FolderEventMoveItem,
-  FolderEventReadApp,
-  FolderEventUpdateApp,
+  FolderEventReadView,
+  FolderEventUpdateView,
   ViewLayoutTypePB,
-} from '@/services/backend/events/flowy-folder';
+} from '@/services/backend/events/flowy-folder2';
 import {
-  AppIdPB,
-  UpdateAppPayloadPB,
   CreateViewPayloadPB,
   RepeatedViewIdPB,
   ViewPB,
   MoveFolderItemPayloadPB,
   MoveFolderItemType,
   FlowyError,
+  ViewIdPB,
+  UpdateViewPayloadPB,
 } from '@/services/backend';
 import { None, Result, Some } from 'ts-results';
 
@@ -23,8 +22,8 @@ export class AppBackendService {
   constructor(public readonly appId: string) {}
 
   getApp = () => {
-    const payload = AppIdPB.fromObject({ value: this.appId });
-    return FolderEventReadApp(payload);
+    const payload = ViewIdPB.fromObject({ value: this.appId });
+    return FolderEventReadView(payload);
   };
 
   createView = async (params: {
@@ -54,9 +53,9 @@ export class AppBackendService {
   };
 
   getAllViews = (): Promise<Result<ViewPB[], FlowyError>> => {
-    const payload = AppIdPB.fromObject({ value: this.appId });
-    return FolderEventReadApp(payload).then((result) => {
-      return result.map((app) => app.belongings.items);
+    const payload = ViewIdPB.fromObject({ value: this.appId });
+    return FolderEventReadView(payload).then((result) => {
+      return result.map((app) => app.belongings);
     });
   };
 
@@ -75,16 +74,16 @@ export class AppBackendService {
   };
 
   update = async (params: { name: string }) => {
-    const payload = UpdateAppPayloadPB.fromObject({ app_id: this.appId, name: params.name });
-    const result = await FolderEventUpdateApp(payload);
+    const payload = UpdateViewPayloadPB.fromObject({ view_id: this.appId, name: params.name });
+    const result = await FolderEventUpdateView(payload);
     if (!result.ok) {
       throw new Error(result.val.msg);
     }
   };
 
   delete = async () => {
-    const payload = AppIdPB.fromObject({ value: this.appId });
-    const result = await FolderEventDeleteApp(payload);
+    const payload = RepeatedViewIdPB.fromObject({ items: [this.appId] });
+    const result = await FolderEventDeleteView(payload);
     if (!result.ok) {
       throw new Error(result.val.msg);
     }

+ 5 - 5
frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts

@@ -1,12 +1,12 @@
 import { Ok, Result } from 'ts-results';
-import { AppPB, FlowyError, FolderNotification } from '@/services/backend';
+import { AppPB, FlowyError, FolderNotification, RepeatedViewPB } from '@/services/backend';
 import { ChangeNotifier } from '$app/utils/change_notifier';
 import { FolderNotificationObserver } from '../notifications/observer';
 
-export type AppUpdateNotifyCallback = (value: Result<AppPB, FlowyError>) => void;
+export type AppUpdateNotifyCallback = (value: Result<RepeatedViewPB, FlowyError>) => void;
 
 export class AppObserver {
-  _appNotifier = new ChangeNotifier<Result<AppPB, FlowyError>>();
+  _appNotifier = new ChangeNotifier<Result<RepeatedViewPB, FlowyError>>();
   _listener?: FolderNotificationObserver;
 
   constructor(public readonly appId: string) {}
@@ -17,9 +17,9 @@ export class AppObserver {
       viewId: this.appId,
       parserHandler: (notification, result) => {
         switch (notification) {
-          case FolderNotification.DidUpdateWorkspaceApps:
+          case FolderNotification.DidUpdateWorkspaceViews:
             if (result.ok) {
-              this._appNotifier?.notify(Ok(AppPB.deserializeBinary(result.val)));
+              this._appNotifier?.notify(Ok(RepeatedViewPB.deserializeBinary(result.val)));
             } else {
               this._appNotifier?.notify(result);
             }

+ 1 - 1
frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_bd_svc.ts

@@ -3,7 +3,7 @@ import {
   FolderEventDeleteView,
   FolderEventDuplicateView,
   FolderEventUpdateView,
-} from '@/services/backend/events/flowy-folder';
+} from '@/services/backend/events/flowy-folder2';
 
 export class ViewBackendService {
   constructor(public readonly viewId: string) {}

+ 13 - 6
frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts

@@ -1,24 +1,31 @@
 import { Err, Ok } from 'ts-results';
 import {
-  FolderEventCreateApp,
+  FolderEventCreateView,
   FolderEventMoveItem,
   FolderEventReadWorkspaceApps,
   FolderEventReadWorkspaces,
-} from '@/services/backend/events/flowy-folder';
-import { CreateAppPayloadPB, WorkspaceIdPB, FlowyError, MoveFolderItemPayloadPB } from '@/services/backend';
+} from '@/services/backend/events/flowy-folder2';
+import {
+  CreateViewPayloadPB,
+  FlowyError,
+  MoveFolderItemPayloadPB,
+  ViewLayoutTypePB,
+  WorkspaceIdPB,
+} from '@/services/backend';
 import assert from 'assert';
 
 export class WorkspaceBackendService {
   constructor(public readonly workspaceId: string) {}
 
   createApp = async (params: { name: string; desc?: string }) => {
-    const payload = CreateAppPayloadPB.fromObject({
-      workspace_id: this.workspaceId,
+    const payload = CreateViewPayloadPB.fromObject({
+      belong_to_id: this.workspaceId,
       name: params.name,
       desc: params.desc || '',
+      layout: ViewLayoutTypePB.Document,
     });
 
-    const result = await FolderEventCreateApp(payload);
+    const result = await FolderEventCreateView(payload);
     if (result.ok) {
       return result.val;
     } else {

+ 12 - 4
frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts

@@ -1,9 +1,17 @@
 import { Ok, Result } from 'ts-results';
-import { AppPB, FolderNotification, RepeatedAppPB, WorkspacePB, FlowyError } from '@/services/backend';
+import {
+  AppPB,
+  FolderNotification,
+  RepeatedAppPB,
+  WorkspacePB,
+  FlowyError,
+  RepeatedViewPB,
+  ViewPB,
+} from '@/services/backend';
 import { ChangeNotifier } from '$app/utils/change_notifier';
 import { FolderNotificationObserver } from '../notifications/observer';
 
-export type AppListNotifyValue = Result<AppPB[], FlowyError>;
+export type AppListNotifyValue = Result<ViewPB[], FlowyError>;
 export type AppListNotifyCallback = (value: AppListNotifyValue) => void;
 export type WorkspaceNotifyValue = Result<WorkspacePB, FlowyError>;
 export type WorkspaceNotifyCallback = (value: WorkspaceNotifyValue) => void;
@@ -33,9 +41,9 @@ export class WorkspaceObserver {
               this.workspaceNotifier?.notify(result);
             }
             break;
-          case FolderNotification.DidUpdateWorkspaceApps:
+          case FolderNotification.DidUpdateWorkspaceViews:
             if (result.ok) {
-              this.appListNotifier?.notify(Ok(RepeatedAppPB.deserializeBinary(result.val).items));
+              this.appListNotifier?.notify(Ok(RepeatedViewPB.deserializeBinary(result.val).items));
             } else {
               this.appListNotifier?.notify(result);
             }

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts

@@ -21,10 +21,10 @@ import {
   FolderEventOpenWorkspace,
   FolderEventReadCurrentWorkspace,
   FolderEventReadWorkspaces,
-} from '@/services/backend/events/flowy-folder';
+} from '@/services/backend/events/flowy-folder2';
 
 export class UserBackendService {
-  constructor(public readonly userId: string) {}
+  constructor(public readonly userId: number) {}
 
   getUserProfile = () => {
     return UserEventGetUserProfile();

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts

@@ -1,9 +1,9 @@
 import { createSlice, PayloadAction } from '@reduxjs/toolkit';
 import { nanoid } from 'nanoid';
-import { WorkspaceSettingPB } from '@/services/backend/models/flowy-folder/workspace';
+import { WorkspaceSettingPB } from '@/services/backend/models/flowy-folder2/workspace';
 
 export interface ICurrentUser {
-  id?: string;
+  id?: number;
   displayName?: string;
   email?: string;
   token?: string;

+ 1 - 1
frontend/appflowy_tauri/src/services/backend/index.ts

@@ -1,6 +1,6 @@
 export * from "./models/flowy-user";
 export * from "./models/flowy-document";
 export * from "./models/flowy-database";
-export * from "./models/flowy-folder";
+export * from "./models/flowy-folder2";
 export * from "./models/flowy-net";
 export * from "./models/flowy-error";

+ 244 - 55
frontend/rust-lib/Cargo.lock

@@ -67,9 +67,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.68"
+version = "1.0.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
+checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
 
 [[package]]
 name = "arrayvec"
@@ -102,7 +102,7 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -113,7 +113,7 @@ checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -298,7 +298,7 @@ dependencies = [
  "borsh-schema-derive-internal",
  "proc-macro-crate",
  "proc-macro2",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -309,7 +309,7 @@ checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -320,7 +320,7 @@ checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -369,7 +369,7 @@ checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -407,9 +407,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.23"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
  "iana-time-zone",
  "js-sys",
@@ -475,7 +475,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -488,6 +488,70 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "collab"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "anyhow",
+ "bytes",
+ "collab-persistence",
+ "lib0",
+ "parking_lot 0.12.1",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "tracing",
+ "y-sync",
+ "yrs",
+]
+
+[[package]]
+name = "collab-derive"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_json",
+ "syn 1.0.109",
+ "yrs",
+]
+
+[[package]]
+name = "collab-folder"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "anyhow",
+ "collab",
+ "collab-derive",
+ "collab-persistence",
+ "parking_lot 0.12.1",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "collab-persistence"
+version = "0.1.0"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45"
+dependencies = [
+ "bincode",
+ "chrono",
+ "lib0",
+ "serde",
+ "sled",
+ "smallvec",
+ "thiserror",
+ "tokio",
+ "yrs",
+]
+
 [[package]]
 name = "color-eyre"
 version = "0.5.11"
@@ -739,7 +803,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "scratch",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -756,7 +820,7 @@ checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -813,7 +877,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -826,7 +890,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustc_version",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -854,7 +918,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1022,7 +1086,7 @@ version = "0.1.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1093,7 +1157,7 @@ dependencies = [
  "serde",
  "serde_json",
  "similar",
- "syn",
+ "syn 1.0.109",
  "tera",
  "toml",
  "walkdir",
@@ -1104,6 +1168,7 @@ name = "flowy-core"
 version = "0.1.0"
 dependencies = [
  "bytes",
+ "collab-persistence",
  "console-subscriber",
  "database-model",
  "flowy-client-ws",
@@ -1111,6 +1176,7 @@ dependencies = [
  "flowy-document",
  "flowy-error",
  "flowy-folder",
+ "flowy-folder2",
  "flowy-net",
  "flowy-revision",
  "flowy-sqlite",
@@ -1192,7 +1258,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde_json",
- "syn",
+ "syn 1.0.109",
  "tokio",
  "trybuild",
  "walkdir",
@@ -1307,6 +1373,35 @@ dependencies = [
  "ws-model",
 ]
 
+[[package]]
+name = "flowy-folder2"
+version = "0.1.0"
+dependencies = [
+ "bytes",
+ "chrono",
+ "collab",
+ "collab-folder",
+ "collab-persistence",
+ "flowy-codegen",
+ "flowy-derive",
+ "flowy-document",
+ "flowy-error",
+ "flowy-folder2",
+ "flowy-notification",
+ "flowy-test",
+ "lazy_static",
+ "lib-dispatch",
+ "lib-infra",
+ "nanoid",
+ "parking_lot 0.12.1",
+ "protobuf",
+ "strum",
+ "strum_macros",
+ "tokio",
+ "tracing",
+ "unicode-segmentation",
+]
+
 [[package]]
 name = "flowy-net"
 version = "0.1.0"
@@ -1324,7 +1419,7 @@ dependencies = [
  "flowy-derive",
  "flowy-document",
  "flowy-error",
- "flowy-folder",
+ "flowy-folder2",
  "flowy-server-sync",
  "flowy-sync",
  "flowy-user",
@@ -1478,7 +1573,7 @@ dependencies = [
  "flowy-client-sync",
  "flowy-core",
  "flowy-document",
- "flowy-folder",
+ "flowy-folder2",
  "flowy-net",
  "flowy-user",
  "futures",
@@ -1503,6 +1598,7 @@ name = "flowy-user"
 version = "0.1.0"
 dependencies = [
  "bytes",
+ "collab-persistence",
  "diesel",
  "diesel_derives",
  "flowy-codegen",
@@ -1568,6 +1664,16 @@ dependencies = [
  "percent-encoding",
 ]
 
+[[package]]
+name = "fs2"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 name = "futures"
 version = "0.3.26"
@@ -1624,7 +1730,7 @@ checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1657,6 +1763,15 @@ dependencies = [
  "slab",
 ]
 
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
 [[package]]
 name = "generic-array"
 version = "0.14.6"
@@ -1684,8 +1799,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
 dependencies = [
  "cfg-if",
+ "js-sys",
  "libc",
  "wasi 0.9.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
 ]
 
 [[package]]
@@ -2166,6 +2283,17 @@ dependencies = [
  "url",
 ]
 
+[[package]]
+name = "lib0"
+version = "0.16.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3994538ae0215990b1c3df6dc45bb5afad77abce3a6ba3335512c5f5d9bfb1d4"
+dependencies = [
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
 [[package]]
 name = "libc"
 version = "0.2.139"
@@ -2285,7 +2413,7 @@ dependencies = [
  "migrations_internals",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2448,7 +2576,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2589,7 +2717,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2664,7 +2792,7 @@ dependencies = [
  "proc-macro-hack",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2703,7 +2831,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2776,7 +2904,7 @@ dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "version_check",
 ]
 
@@ -2799,9 +2927,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.49"
+version = "1.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
+checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
 dependencies = [
  "unicode-ident",
 ]
@@ -2826,7 +2954,7 @@ dependencies = [
  "itertools",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2942,7 +3070,7 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2964,14 +3092,14 @@ checksum = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -3218,7 +3346,7 @@ checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3362,9 +3490,9 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
 
 [[package]]
 name = "serde"
-version = "1.0.152"
+version = "1.0.158"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
 dependencies = [
  "serde_derive",
 ]
@@ -3392,20 +3520,20 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.158"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.8",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
 dependencies = [
  "itoa 1.0.5",
  "ryu",
@@ -3420,7 +3548,7 @@ checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3454,7 +3582,7 @@ checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3520,6 +3648,22 @@ dependencies = [
  "autocfg",
 ]
 
+[[package]]
+name = "sled"
+version = "0.34.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
+dependencies = [
+ "crc32fast",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "fs2",
+ "fxhash",
+ "libc",
+ "log",
+ "parking_lot 0.11.2",
+]
+
 [[package]]
 name = "slug"
 version = "0.1.4"
@@ -3529,6 +3673,15 @@ dependencies = [
  "deunicode",
 ]
 
+[[package]]
+name = "smallstr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f"
+dependencies = [
+ "smallvec",
+]
+
 [[package]]
 name = "smallvec"
 version = "1.10.0"
@@ -3566,7 +3719,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3580,6 +3733,17 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "syn"
+version = "2.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "sync_wrapper"
 version = "0.1.2"
@@ -3652,22 +3816,22 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -3765,7 +3929,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3940,7 +4104,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4306,7 +4470,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "wasm-bindgen-shared",
 ]
 
@@ -4340,7 +4504,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -4504,6 +4668,17 @@ dependencies = [
  "serde_repr",
 ]
 
+[[package]]
+name = "y-sync"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e77a143afe4dde83bc987ad3119228d0f107053a3da131a00738cb2d7f496641"
+dependencies = [
+ "lib0",
+ "thiserror",
+ "yrs",
+]
+
 [[package]]
 name = "yaml-rust"
 version = "0.4.5"
@@ -4512,3 +4687,17 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
 dependencies = [
  "linked-hash-map",
 ]
+
+[[package]]
+name = "yrs"
+version = "0.16.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2b23ac465bed6c0ffbb9fbd80ec808bd89b37b823a420b16917d1806d76d75"
+dependencies = [
+ "atomic_refcell",
+ "lib0",
+ "rand 0.7.3",
+ "smallstr",
+ "smallvec",
+ "thiserror",
+]

+ 9 - 2
frontend/rust-lib/Cargo.toml

@@ -8,7 +8,8 @@ members = [
   "flowy-user",
   "flowy-test",
   "flowy-sqlite",
-  "flowy-folder",
+#  "flowy-folder",
+  "flowy-folder2",
   "flowy-notification",
   "flowy-document",
   "flowy-error",
@@ -34,4 +35,10 @@ opt-level = 3
 #strip = "debuginfo"
 ## For from-scratch builds, incremental adds an extra dependency-tracking overhead. It also significantly increases
 ## the amount of IO and the size of ./target, which make caching less effective.
-incremental = false
+incremental = false
+
+
+[patch.crates-io]
+collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" }
+collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" }
+collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" }

+ 4 - 0
frontend/rust-lib/flowy-core/Cargo.toml

@@ -11,6 +11,7 @@ lib-log = { path = "../lib-log" }
 flowy-user = { path = "../flowy-user" }
 flowy-net = { path = "../flowy-net" }
 flowy-folder = { path = "../flowy-folder" }
+flowy-folder2 = { path = "../flowy-folder2" }
 flowy-database = { path = "../flowy-database" }
 database-model = { path = "../../../shared-lib/database-model" }
 user-model = { path = "../../../shared-lib/user-model" }
@@ -20,6 +21,7 @@ flowy-document = { path = "../flowy-document" }
 flowy-revision = { path = "../flowy-revision" }
 flowy-error = { path = "../flowy-error", features = ["adaptor_ws"] }
 flowy-task = { path = "../flowy-task" }
+collab-persistence = { version = "0.1.0" }
 
 tracing = { version = "0.1", features = ["log"] }
 futures-core = { version = "0.3", default-features = false }
@@ -45,6 +47,7 @@ dart = [
     "flowy-user/dart",
     "flowy-net/dart",
     "flowy-folder/dart",
+    "flowy-folder2/dart",
     "flowy-database/dart",
     "flowy-document/dart",
 ]
@@ -52,6 +55,7 @@ ts = [
     "flowy-user/ts",
     "flowy-net/ts",
     "flowy-folder/ts",
+    "flowy-folder2/ts",
     "flowy-database/ts",
     "flowy-document/ts",
 ]

+ 1 - 1
frontend/rust-lib/flowy-core/src/deps_resolve/document_deps.rs

@@ -61,7 +61,7 @@ impl DocumentUser for BlockUserImpl {
     Ok(doc_dir)
   }
 
-  fn user_id(&self) -> Result<String, FlowyError> {
+  fn user_id(&self) -> Result<i64, FlowyError> {
     self.0.user_id()
   }
 

+ 258 - 0
frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs

@@ -0,0 +1,258 @@
+use bytes::Bytes;
+use collab_persistence::CollabKV;
+use database_model::BuildDatabaseContext;
+use flowy_database::entities::LayoutTypePB;
+use flowy_database::manager::{create_new_database, link_existing_database, DatabaseManager};
+use flowy_database::util::{make_default_board, make_default_calendar, make_default_grid};
+use flowy_document::editor::make_transaction_from_document_content;
+use flowy_document::DocumentManager;
+use flowy_error::FlowyError;
+
+use flowy_folder2::manager::{Folder2Manager, FolderUser};
+use flowy_folder2::view_ext::{ViewDataProcessor, ViewDataProcessorMap};
+use flowy_folder2::ViewLayout;
+use flowy_user::services::UserSession;
+use lib_infra::future::FutureResult;
+use revision_model::Revision;
+use std::collections::HashMap;
+use std::convert::TryFrom;
+use std::sync::Arc;
+
+pub struct Folder2DepsResolver();
+impl Folder2DepsResolver {
+  pub async fn resolve(
+    user_session: Arc<UserSession>,
+    document_manager: &Arc<DocumentManager>,
+    database_manager: &Arc<DatabaseManager>,
+  ) -> Arc<Folder2Manager> {
+    let user: Arc<dyn FolderUser> = Arc::new(FolderUserImpl(user_session.clone()));
+
+    let view_data_processor =
+      make_view_data_processor(document_manager.clone(), database_manager.clone());
+    Arc::new(
+      Folder2Manager::new(user.clone(), view_data_processor)
+        .await
+        .unwrap(),
+    )
+  }
+}
+
+fn make_view_data_processor(
+  document_manager: Arc<DocumentManager>,
+  database_manager: Arc<DatabaseManager>,
+) -> ViewDataProcessorMap {
+  let mut map: HashMap<ViewLayout, Arc<dyn ViewDataProcessor + Send + Sync>> = HashMap::new();
+
+  let document_processor = Arc::new(DocumentViewDataProcessor(document_manager));
+  map.insert(ViewLayout::Document, document_processor);
+
+  let database_processor = Arc::new(DatabaseViewDataProcessor(database_manager));
+  map.insert(ViewLayout::Board, database_processor.clone());
+  map.insert(ViewLayout::Grid, database_processor.clone());
+  map.insert(ViewLayout::Calendar, database_processor);
+  Arc::new(map)
+}
+
+struct FolderUserImpl(Arc<UserSession>);
+impl FolderUser for FolderUserImpl {
+  fn user_id(&self) -> Result<i64, FlowyError> {
+    self
+      .0
+      .user_id()
+      .map_err(|e| FlowyError::internal().context(e))
+  }
+
+  fn token(&self) -> Result<String, FlowyError> {
+    self
+      .0
+      .token()
+      .map_err(|e| FlowyError::internal().context(e))
+  }
+
+  fn kv_db(&self) -> Result<Arc<CollabKV>, FlowyError> {
+    self.0.get_kv_db()
+  }
+}
+
+struct DocumentViewDataProcessor(Arc<DocumentManager>);
+impl ViewDataProcessor for DocumentViewDataProcessor {
+  fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
+    let manager = self.0.clone();
+    let view_id = view_id.to_string();
+    FutureResult::new(async move {
+      manager.close_document_editor(view_id).await?;
+      Ok(())
+    })
+  }
+
+  fn get_view_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError> {
+    let manager = self.0.clone();
+    let view_id = view_id.to_string();
+    FutureResult::new(async move {
+      let editor = manager.open_document_editor(view_id).await?;
+      let document_data = Bytes::from(editor.duplicate().await?);
+      Ok(document_data)
+    })
+  }
+
+  fn create_view_with_build_in_data(
+    &self,
+    _user_id: i64,
+    view_id: &str,
+    _name: &str,
+    layout: ViewLayout,
+    _ext: HashMap<String, String>,
+  ) -> FutureResult<(), FlowyError> {
+    debug_assert_eq!(layout, ViewLayout::Document);
+    let view_id = view_id.to_string();
+    let manager = self.0.clone();
+    let document_content = self.0.initial_document_content();
+    FutureResult::new(async move {
+      let delta_data = Bytes::from(document_content);
+      let revision = Revision::initial_revision(&view_id, delta_data);
+      manager.create_document(view_id, vec![revision]).await?;
+      Ok(())
+    })
+  }
+
+  fn create_view_with_custom_data(
+    &self,
+    _user_id: i64,
+    view_id: &str,
+    _name: &str,
+    data: Vec<u8>,
+    layout: ViewLayout,
+    _ext: HashMap<String, String>,
+  ) -> FutureResult<(), FlowyError> {
+    debug_assert_eq!(layout, ViewLayout::Document);
+    let view_data = match String::from_utf8(data) {
+      Ok(content) => match make_transaction_from_document_content(&content) {
+        Ok(transaction) => transaction.to_bytes().unwrap_or_else(|_| vec![]),
+        Err(_) => vec![],
+      },
+      Err(_) => vec![],
+    };
+
+    let revision = Revision::initial_revision(view_id, Bytes::from(view_data));
+    let view_id = view_id.to_string();
+    let manager = self.0.clone();
+
+    FutureResult::new(async move {
+      manager.create_document(view_id, vec![revision]).await?;
+      Ok(())
+    })
+  }
+}
+
+struct DatabaseViewDataProcessor(Arc<DatabaseManager>);
+impl ViewDataProcessor for DatabaseViewDataProcessor {
+  fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
+    let database_manager = self.0.clone();
+    let view_id = view_id.to_string();
+    FutureResult::new(async move {
+      database_manager.close_database_view(view_id).await?;
+      Ok(())
+    })
+  }
+
+  fn get_view_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError> {
+    let database_manager = self.0.clone();
+    let view_id = view_id.to_owned();
+    FutureResult::new(async move {
+      let editor = database_manager.open_database_view(&view_id).await?;
+      let delta_bytes = editor.duplicate_database(&view_id).await?;
+      Ok(delta_bytes.into())
+    })
+  }
+
+  /// Create a database view with build-in data.
+  /// If the ext contains the {"database_id": "xx"}, then it will link to
+  /// the existing database. The data of the database will be shared within
+  /// these references views.
+  fn create_view_with_build_in_data(
+    &self,
+    _user_id: i64,
+    view_id: &str,
+    name: &str,
+    layout: ViewLayout,
+    ext: HashMap<String, String>,
+  ) -> FutureResult<(), FlowyError> {
+    let view_id = view_id.to_string();
+    let name = name.to_string();
+    let database_manager = self.0.clone();
+    match DatabaseExtParams::from_map(ext).map(|params| params.database_id) {
+      None => {
+        let (build_context, layout) = match layout {
+          ViewLayout::Grid => (make_default_grid(), LayoutTypePB::Grid),
+          ViewLayout::Board => (make_default_board(), LayoutTypePB::Board),
+          ViewLayout::Calendar => (make_default_calendar(), LayoutTypePB::Calendar),
+          ViewLayout::Document => {
+            return FutureResult::new(async move {
+              Err(FlowyError::internal().context(format!("Can't handle {:?} layout type", layout)))
+            });
+          },
+        };
+        FutureResult::new(async move {
+          create_new_database(&view_id, name, layout, database_manager, build_context).await
+        })
+      },
+      Some(database_id) => {
+        let layout = layout_type_from_view_layout(layout);
+        FutureResult::new(async move {
+          link_existing_database(&view_id, name, &database_id, layout, database_manager).await
+        })
+      },
+    }
+  }
+
+  /// Create a database view with custom data.
+  /// If the ext contains the {"database_id": "xx"}, then it will link
+  /// to the existing database. The data of the database will be shared
+  /// within these references views.
+  fn create_view_with_custom_data(
+    &self,
+    _user_id: i64,
+    view_id: &str,
+    name: &str,
+    data: Vec<u8>,
+    layout: ViewLayout,
+    ext: HashMap<String, String>,
+  ) -> FutureResult<(), FlowyError> {
+    let view_id = view_id.to_string();
+    let database_manager = self.0.clone();
+    let layout = layout_type_from_view_layout(layout);
+    let name = name.to_string();
+    match DatabaseExtParams::from_map(ext).map(|params| params.database_id) {
+      None => FutureResult::new(async move {
+        let bytes = Bytes::from(data);
+        let build_context = BuildDatabaseContext::try_from(bytes)?;
+        let _ = create_new_database(&view_id, name, layout, database_manager, build_context).await;
+        Ok(())
+      }),
+      Some(database_id) => FutureResult::new(async move {
+        link_existing_database(&view_id, name, &database_id, layout, database_manager).await
+      }),
+    }
+  }
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct DatabaseExtParams {
+  database_id: String,
+}
+
+impl DatabaseExtParams {
+  pub fn from_map(map: HashMap<String, String>) -> Option<Self> {
+    let value = serde_json::to_value(map).ok()?;
+    serde_json::from_value::<Self>(value).ok()
+  }
+}
+
+pub fn layout_type_from_view_layout(layout: ViewLayout) -> LayoutTypePB {
+  match layout {
+    ViewLayout::Grid => LayoutTypePB::Grid,
+    ViewLayout::Board => LayoutTypePB::Board,
+    ViewLayout::Calendar => LayoutTypePB::Calendar,
+    ViewLayout::Document => LayoutTypePB::Grid,
+  }
+}

+ 1 - 1
frontend/rust-lib/flowy-core/src/deps_resolve/grid_deps.rs

@@ -46,7 +46,7 @@ impl DatabaseDBConnection for DatabaseDBConnectionImpl {
 
 struct GridUserImpl(Arc<UserSession>);
 impl DatabaseUser for GridUserImpl {
-  fn user_id(&self) -> Result<String, FlowyError> {
+  fn user_id(&self) -> Result<i64, FlowyError> {
     self.0.user_id()
   }
 

+ 2 - 2
frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs

@@ -1,10 +1,10 @@
 mod document_deps;
-mod folder_deps;
+mod folder2_deps;
 mod grid_deps;
 mod user_deps;
 mod util;
 
 pub use document_deps::*;
-pub use folder_deps::*;
+pub use folder2_deps::*;
 pub use grid_deps::*;
 pub use user_deps::*;

+ 44 - 58
frontend/rust-lib/flowy-core/src/lib.rs

@@ -1,13 +1,15 @@
 mod deps_resolve;
 pub mod module;
 use crate::deps_resolve::*;
+
 use flowy_client_ws::{listen_on_websocket, FlowyWebSocketConnect, NetworkType};
+use flowy_database::entities::LayoutTypePB;
 use flowy_database::manager::DatabaseManager;
 use flowy_document::entities::DocumentVersionPB;
 use flowy_document::{DocumentConfig, DocumentManager};
 use flowy_error::FlowyResult;
-use flowy_folder::entities::{ViewDataFormatPB, ViewLayoutTypePB};
-use flowy_folder::{errors::FlowyError, manager::FolderManager};
+use flowy_folder::errors::FlowyError;
+use flowy_folder2::manager::Folder2Manager;
 pub use flowy_net::get_client_server_configuration;
 use flowy_net::local_server::LocalServer;
 use flowy_net::ClientServerConfiguration;
@@ -16,8 +18,6 @@ use flowy_user::event_map::UserStatusCallback;
 use flowy_user::services::{UserSession, UserSessionConfig};
 use lib_dispatch::prelude::*;
 use lib_dispatch::runtime::tokio_default_runtime;
-
-use flowy_database::entities::LayoutTypePB;
 use lib_infra::future::{to_fut, Fut};
 use module::make_plugins;
 pub use module::*;
@@ -89,6 +89,8 @@ fn create_log_filter(level: String, with_crates: Vec<String>) -> String {
     .collect::<Vec<String>>();
   filters.push(format!("flowy_core={}", level));
   filters.push(format!("flowy_folder={}", level));
+  filters.push(format!("flowy_folder2={}", level));
+  filters.push(format!("collab_folder={}", level));
   filters.push(format!("flowy_user={}", level));
   filters.push(format!("flowy_document={}", level));
   filters.push(format!("flowy_database={}", level));
@@ -106,7 +108,7 @@ fn create_log_filter(level: String, with_crates: Vec<String>) -> String {
 
   filters.push(format!("dart_ffi={}", "info"));
   filters.push(format!("flowy_sqlite={}", "info"));
-  filters.push(format!("flowy_net={}", "info"));
+  filters.push(format!("flowy_net={}", level));
   #[cfg(feature = "profiling")]
   filters.push(format!("tokio={}", level));
 
@@ -122,7 +124,7 @@ pub struct AppFlowyCore {
   pub config: AppFlowyCoreConfig,
   pub user_session: Arc<UserSession>,
   pub document_manager: Arc<DocumentManager>,
-  pub folder_manager: Arc<FolderManager>,
+  pub folder_manager: Arc<Folder2Manager>,
   pub database_manager: Arc<DatabaseManager>,
   pub event_dispatcher: Arc<AFPluginDispatcher>,
   pub ws_conn: Arc<FlowyWebSocketConnect>,
@@ -162,15 +164,9 @@ impl AppFlowyCore {
         )
         .await;
 
-        let folder_manager = FolderDepsResolver::resolve(
-          local_server.clone(),
-          user_session.clone(),
-          &config.server_config,
-          &ws_conn,
-          &document_manager,
-          &database_manager,
-        )
-        .await;
+        let folder_manager =
+          Folder2DepsResolver::resolve(user_session.clone(), &document_manager, &database_manager)
+            .await;
 
         if let Some(local_server) = local_server.as_ref() {
           local_server.run();
@@ -232,11 +228,11 @@ impl AppFlowyCore {
 fn _start_listening(
   event_dispatcher: &AFPluginDispatcher,
   ws_conn: &Arc<FlowyWebSocketConnect>,
-  folder_manager: &Arc<FolderManager>,
+  folder_manager: &Arc<Folder2Manager>,
 ) {
   let subscribe_network_type = ws_conn.subscribe_network_ty();
   let folder_manager = folder_manager.clone();
-  let cloned_folder_manager = folder_manager;
+  let _cloned_folder_manager = folder_manager;
   let ws_conn = ws_conn.clone();
 
   event_dispatcher.spawn(async move {
@@ -244,7 +240,7 @@ fn _start_listening(
   });
 
   event_dispatcher.spawn(async move {
-    _listen_network_status(subscribe_network_type, cloned_folder_manager).await;
+    _listen_network_status(subscribe_network_type).await;
   });
 }
 
@@ -263,10 +259,7 @@ fn mk_local_server(
   }
 }
 
-async fn _listen_network_status(
-  mut subscribe: broadcast::Receiver<NetworkType>,
-  _core: Arc<FolderManager>,
-) {
+async fn _listen_network_status(mut subscribe: broadcast::Receiver<NetworkType>) {
   while let Ok(_new_type) = subscribe.recv().await {
     // core.network_state_changed(new_type);
   }
@@ -301,41 +294,33 @@ fn mk_user_session(
 
 struct UserStatusListener {
   document_manager: Arc<DocumentManager>,
-  folder_manager: Arc<FolderManager>,
+  folder_manager: Arc<Folder2Manager>,
   database_manager: Arc<DatabaseManager>,
   ws_conn: Arc<FlowyWebSocketConnect>,
+  #[allow(dead_code)]
   config: AppFlowyCoreConfig,
 }
 
 impl UserStatusListener {
-  async fn did_sign_in(&self, token: &str, user_id: &str) -> FlowyResult<()> {
-    self.folder_manager.initialize(user_id, token).await?;
+  async fn did_sign_in(&self, token: &str, user_id: i64) -> FlowyResult<()> {
+    self.folder_manager.initialize(user_id).await?;
     self.document_manager.initialize(user_id).await?;
-
     let cloned_folder_manager = self.folder_manager.clone();
     let get_views_fn = to_fut(async move {
       cloned_folder_manager
-        .get_current_workspace()
+        .get_current_workspace_views()
         .await
-        .map(|workspace| {
-          workspace
-            .apps
-            .items
-            .into_iter()
-            .flat_map(|app| app.belongings.items)
-            .flat_map(|view| match view.layout {
-              ViewLayoutTypePB::Grid | ViewLayoutTypePB::Board | ViewLayoutTypePB::Calendar => {
-                Some((
-                  view.id,
-                  view.name,
-                  layout_type_from_view_layout(view.layout),
-                ))
-              },
-              _ => None,
-            })
-            .collect::<Vec<(String, String, LayoutTypePB)>>()
-        })
         .unwrap_or_default()
+        .into_iter()
+        .filter(|view| view.layout.is_database())
+        .map(|view| {
+          (
+            view.id,
+            view.name,
+            layout_type_from_view_layout(view.layout),
+          )
+        })
+        .collect::<Vec<(String, String, LayoutTypePB)>>()
     });
     self
       .database_manager
@@ -349,32 +334,28 @@ impl UserStatusListener {
   }
 
   async fn did_sign_up(&self, user_profile: &UserProfile) -> FlowyResult<()> {
-    let view_data_type = match self.config.document.version {
-      DocumentVersionPB::V0 => ViewDataFormatPB::DeltaFormat,
-      DocumentVersionPB::V1 => ViewDataFormatPB::NodeFormat,
-    };
     self
       .folder_manager
-      .initialize_with_new_user(&user_profile.id, &user_profile.token, view_data_type)
+      .initialize_with_new_user(user_profile.id, &user_profile.token)
       .await?;
     self
       .document_manager
-      .initialize_with_new_user(&user_profile.id, &user_profile.token)
+      .initialize_with_new_user(user_profile.id, &user_profile.token)
       .await?;
 
     self
       .database_manager
-      .initialize_with_new_user(&user_profile.id, &user_profile.token)
+      .initialize_with_new_user(user_profile.id, &user_profile.token)
       .await?;
 
     self
       .ws_conn
-      .start(user_profile.token.clone(), user_profile.id.clone())
+      .start(user_profile.token.clone(), user_profile.id)
       .await?;
     Ok(())
   }
 
-  async fn did_expired(&self, _token: &str, user_id: &str) -> FlowyResult<()> {
+  async fn did_expired(&self, _token: &str, user_id: i64) -> FlowyResult<()> {
     self.folder_manager.clear(user_id).await;
     self.ws_conn.stop().await;
     Ok(())
@@ -386,11 +367,11 @@ struct UserStatusCallbackImpl {
 }
 
 impl UserStatusCallback for UserStatusCallbackImpl {
-  fn did_sign_in(&self, token: &str, user_id: &str) -> Fut<FlowyResult<()>> {
+  fn did_sign_in(&self, token: &str, user_id: i64) -> Fut<FlowyResult<()>> {
     let listener = self.listener.clone();
     let token = token.to_owned();
     let user_id = user_id.to_owned();
-    to_fut(async move { listener.did_sign_in(&token, &user_id).await })
+    to_fut(async move { listener.did_sign_in(&token, user_id).await })
   }
 
   fn did_sign_up(&self, user_profile: &UserProfile) -> Fut<FlowyResult<()>> {
@@ -399,10 +380,15 @@ impl UserStatusCallback for UserStatusCallbackImpl {
     to_fut(async move { listener.did_sign_up(&user_profile).await })
   }
 
-  fn did_expired(&self, token: &str, user_id: &str) -> Fut<FlowyResult<()>> {
+  fn did_expired(&self, token: &str, user_id: i64) -> Fut<FlowyResult<()>> {
     let listener = self.listener.clone();
     let token = token.to_owned();
     let user_id = user_id.to_owned();
-    to_fut(async move { listener.did_expired(&token, &user_id).await })
+    to_fut(async move { listener.did_expired(&token, user_id).await })
+  }
+
+  fn will_migrated(&self, _token: &str, _old_user_id: &str, _user_id: i64) -> Fut<FlowyResult<()>> {
+    // Read the folder data
+    todo!()
   }
 }

Some files were not shown because too many files changed in this diff