Browse Source

Merge branch 'main' into add_workspace_settings

Ian Su 3 years ago
parent
commit
0d216e5647
100 changed files with 616 additions and 436 deletions
  1. 3 1
      frontend/.vscode/launch.json
  2. 2 0
      frontend/Makefile.toml
  3. 39 0
      frontend/app_flowy/lib/core/folder_notification.dart
  4. 39 0
      frontend/app_flowy/lib/core/grid_notification.dart
  5. 0 62
      frontend/app_flowy/lib/core/notification_helper.dart
  6. 39 0
      frontend/app_flowy/lib/core/user_notification.dart
  7. 1 1
      frontend/app_flowy/lib/plugin/plugin.dart
  8. 7 10
      frontend/app_flowy/lib/startup/deps_resolver.dart
  9. 91 58
      frontend/app_flowy/lib/user/application/user_listener.dart
  10. 1 1
      frontend/app_flowy/lib/user/application/user_service.dart
  11. 1 1
      frontend/app_flowy/lib/user/presentation/router.dart
  12. 1 4
      frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart
  13. 1 1
      frontend/app_flowy/lib/user/presentation/welcome_screen.dart
  14. 2 2
      frontend/app_flowy/lib/workspace/application/app/app_bloc.dart
  15. 3 3
      frontend/app_flowy/lib/workspace/application/app/app_listener.dart
  16. 2 2
      frontend/app_flowy/lib/workspace/application/app/app_service.dart
  17. 2 2
      frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart
  18. 1 1
      frontend/app_flowy/lib/workspace/application/doc/doc_service.dart
  19. 1 1
      frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart
  20. 1 2
      frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart
  21. 1 1
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_listener.dart
  22. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart
  23. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart
  24. 1 1
      frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart
  25. 1 1
      frontend/app_flowy/lib/workspace/application/grid/grid_service.dart
  26. 1 1
      frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart
  27. 5 7
      frontend/app_flowy/lib/workspace/application/home/home_bloc.dart
  28. 2 2
      frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart
  29. 40 27
      frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart
  30. 1 1
      frontend/app_flowy/lib/workspace/application/menu/menu_view_section_bloc.dart
  31. 1 1
      frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart
  32. 2 2
      frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart
  33. 1 2
      frontend/app_flowy/lib/workspace/application/trash/trash_service.dart
  34. 1 1
      frontend/app_flowy/lib/workspace/application/view/view_bloc.dart
  35. 1 1
      frontend/app_flowy/lib/workspace/application/view/view_ext.dart
  36. 2 2
      frontend/app_flowy/lib/workspace/application/view/view_listener.dart
  37. 1 1
      frontend/app_flowy/lib/workspace/application/view/view_service.dart
  38. 6 6
      frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart
  39. 38 62
      frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart
  40. 3 3
      frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart
  41. 1 1
      frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart
  42. 1 0
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart
  43. 1 1
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart
  44. 1 1
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart
  45. 1 1
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart
  46. 2 2
      frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart
  47. 2 2
      frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart
  48. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/board/board.dart
  49. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/board/src/board_page.dart
  50. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart
  51. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart
  52. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart
  53. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart
  54. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart
  55. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart
  56. 1 0
      frontend/app_flowy/macos/Runner.xcodeproj/project.pbxproj
  57. 1 2
      frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart
  58. 1 0
      frontend/rust-lib/Cargo.lock
  59. 1 0
      frontend/rust-lib/flowy-folder/Cargo.toml
  60. 25 9
      frontend/rust-lib/flowy-folder/src/entities/app.rs
  61. 1 0
      frontend/rust-lib/flowy-folder/src/entities/mod.rs
  62. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/app/app_color_style.rs
  63. 1 0
      frontend/rust-lib/flowy-folder/src/entities/parser/app/app_desc.rs
  64. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/app/app_id.rs
  65. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/app/app_name.rs
  66. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/app/mod.rs
  67. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/mod.rs
  68. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/trash/mod.rs
  69. 2 0
      frontend/rust-lib/flowy-folder/src/entities/parser/trash/trash_id.rs
  70. 0 4
      frontend/rust-lib/flowy-folder/src/entities/parser/view/mod.rs
  71. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/view/view_desc.rs
  72. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/view/view_id.rs
  73. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/view/view_name.rs
  74. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/view/view_thumbnail.rs
  75. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/workspace/mod.rs
  76. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/workspace/workspace_desc.rs
  77. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/workspace/workspace_id.rs
  78. 0 0
      frontend/rust-lib/flowy-folder/src/entities/parser/workspace/workspace_name.rs
  79. 66 5
      frontend/rust-lib/flowy-folder/src/entities/trash.rs
  80. 40 21
      frontend/rust-lib/flowy-folder/src/entities/view.rs
  81. 0 0
      frontend/rust-lib/flowy-folder/src/entities/view_info.rs
  82. 14 6
      frontend/rust-lib/flowy-folder/src/entities/workspace.rs
  83. 1 3
      frontend/rust-lib/flowy-folder/src/lib.rs
  84. 1 1
      frontend/rust-lib/flowy-folder/src/manager.rs
  85. 23 26
      frontend/rust-lib/flowy-folder/src/services/persistence/version_1/trash_sql.rs
  86. 6 6
      frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs
  87. 1 1
      frontend/rust-lib/flowy-folder/src/services/trash/controller.rs
  88. 17 12
      frontend/rust-lib/flowy-folder/src/services/view/controller.rs
  89. 2 2
      frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs
  90. 1 1
      frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs
  91. 5 5
      frontend/rust-lib/flowy-folder/src/services/workspace/event_handler.rs
  92. 1 1
      frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs
  93. 8 8
      frontend/rust-lib/flowy-folder/tests/workspace/script.rs
  94. 1 1
      frontend/rust-lib/flowy-net/src/http_server/folder.rs
  95. 5 5
      frontend/rust-lib/flowy-net/src/local_server/server.rs
  96. 1 1
      frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs
  97. 1 1
      frontend/rust-lib/flowy-test/src/helper.rs
  98. 1 1
      frontend/rust-lib/flowy-user/src/handlers/user_handler.rs
  99. 24 20
      frontend/rust-lib/flowy-user/src/services/user_session.rs
  100. 0 2
      shared-lib/flowy-folder-data-model/Flowy.toml

+ 3 - 1
frontend/.vscode/launch.json

@@ -62,8 +62,10 @@
         {
             "name": "AF: app_flowy (profile mode)",
             "request": "launch",
+            "program": "./lib/main.dart",
             "type": "dart",
-            "flutterMode": "profile"
+            "flutterMode": "profile",
+            "cwd": "${workspaceRoot}/app_flowy"
         },
     ]
 }

+ 2 - 0
frontend/Makefile.toml

@@ -52,6 +52,7 @@ RUST_COMPILE_TARGET = "aarch64-apple-darwin"
 BUILD_FLAG = "debug"
 FLUTTER_OUTPUT_DIR = "Debug"
 PRODUCT_EXT = "app"
+BUILD_ARCHS = "arm64"
 
 [env.development-mac-x86_64]
 RUST_LOG = "info"
@@ -60,6 +61,7 @@ RUST_COMPILE_TARGET = "x86_64-apple-darwin"
 BUILD_FLAG = "debug"
 FLUTTER_OUTPUT_DIR = "Debug"
 PRODUCT_EXT = "app"
+BUILD_ARCHS = "x86_64"
 
 [env.production-mac-arm64]
 BUILD_FLAG = "release"

+ 39 - 0
frontend/app_flowy/lib/core/folder_notification.dart

@@ -0,0 +1,39 @@
+import 'dart:async';
+import 'dart:typed_data';
+import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
+import 'package:dartz/dartz.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
+import 'package:flowy_sdk/rust_stream.dart';
+
+import 'notification_helper.dart';
+
+// Folder
+typedef FolderNotificationCallback = void Function(FolderNotification, Either<Uint8List, FlowyError>);
+
+class FolderNotificationParser extends NotificationParser<FolderNotification, FlowyError> {
+  FolderNotificationParser({String? id, required FolderNotificationCallback callback})
+      : super(
+          id: id,
+          callback: callback,
+          tyParser: (ty) => FolderNotification.valueOf(ty),
+          errorParser: (bytes) => FlowyError.fromBuffer(bytes),
+        );
+}
+
+typedef FolderNotificationHandler = Function(FolderNotification ty, Either<Uint8List, FlowyError> result);
+
+class FolderNotificationListener {
+  StreamSubscription<SubscribeObject>? _subscription;
+  FolderNotificationParser? _parser;
+
+  FolderNotificationListener({required String objectId, required FolderNotificationHandler handler})
+      : _parser = FolderNotificationParser(id: objectId, callback: handler) {
+    _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
+  }
+
+  Future<void> stop() async {
+    _parser = null;
+    await _subscription?.cancel();
+  }
+}

+ 39 - 0
frontend/app_flowy/lib/core/grid_notification.dart

@@ -0,0 +1,39 @@
+import 'dart:async';
+import 'dart:typed_data';
+import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
+import 'package:dartz/dartz.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
+import 'package:flowy_sdk/rust_stream.dart';
+
+import 'notification_helper.dart';
+
+// Grid
+typedef GridNotificationCallback = void Function(GridNotification, Either<Uint8List, FlowyError>);
+
+class GridNotificationParser extends NotificationParser<GridNotification, FlowyError> {
+  GridNotificationParser({String? id, required GridNotificationCallback callback})
+      : super(
+          id: id,
+          callback: callback,
+          tyParser: (ty) => GridNotification.valueOf(ty),
+          errorParser: (bytes) => FlowyError.fromBuffer(bytes),
+        );
+}
+
+typedef GridNotificationHandler = Function(GridNotification ty, Either<Uint8List, FlowyError> result);
+
+class GridNotificationListener {
+  StreamSubscription<SubscribeObject>? _subscription;
+  GridNotificationParser? _parser;
+
+  GridNotificationListener({required String objectId, required GridNotificationHandler handler})
+      : _parser = GridNotificationParser(id: objectId, callback: handler) {
+    _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
+  }
+
+  Future<void> stop() async {
+    _parser = null;
+    await _subscription?.cancel();
+  }
+}

+ 0 - 62
frontend/app_flowy/lib/core/notification_helper.dart

@@ -1,68 +1,6 @@
-import 'dart:async';
 import 'dart:typed_data';
 import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
-import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
 import 'package:dartz/dartz.dart';
-import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
-import 'package:flowy_sdk/rust_stream.dart';
-
-// User
-typedef UserNotificationCallback = void Function(UserNotification, Either<Uint8List, FlowyError>);
-
-class UserNotificationParser extends NotificationParser<UserNotification, FlowyError> {
-  UserNotificationParser({required String id, required UserNotificationCallback callback})
-      : super(
-          id: id,
-          callback: callback,
-          tyParser: (ty) => UserNotification.valueOf(ty),
-          errorParser: (bytes) => FlowyError.fromBuffer(bytes),
-        );
-}
-
-// Folder
-typedef FolderNotificationCallback = void Function(FolderNotification, Either<Uint8List, FlowyError>);
-
-class FolderNotificationParser extends NotificationParser<FolderNotification, FlowyError> {
-  FolderNotificationParser({String? id, required FolderNotificationCallback callback})
-      : super(
-          id: id,
-          callback: callback,
-          tyParser: (ty) => FolderNotification.valueOf(ty),
-          errorParser: (bytes) => FlowyError.fromBuffer(bytes),
-        );
-}
-
-// Grid
-typedef GridNotificationCallback = void Function(GridNotification, Either<Uint8List, FlowyError>);
-
-class GridNotificationParser extends NotificationParser<GridNotification, FlowyError> {
-  GridNotificationParser({String? id, required GridNotificationCallback callback})
-      : super(
-          id: id,
-          callback: callback,
-          tyParser: (ty) => GridNotification.valueOf(ty),
-          errorParser: (bytes) => FlowyError.fromBuffer(bytes),
-        );
-}
-
-typedef GridNotificationHandler = Function(GridNotification ty, Either<Uint8List, FlowyError> result);
-
-class GridNotificationListener {
-  StreamSubscription<SubscribeObject>? _subscription;
-  GridNotificationParser? _parser;
-
-  GridNotificationListener({required String objectId, required GridNotificationHandler handler})
-      : _parser = GridNotificationParser(id: objectId, callback: handler) {
-    _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
-  }
-
-  Future<void> stop() async {
-    _parser = null;
-    await _subscription?.cancel();
-  }
-}
 
 class NotificationParser<T, E> {
   String? id;

+ 39 - 0
frontend/app_flowy/lib/core/user_notification.dart

@@ -0,0 +1,39 @@
+import 'dart:async';
+import 'dart:typed_data';
+import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
+import 'package:dartz/dartz.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/rust_stream.dart';
+
+import 'notification_helper.dart';
+
+// User
+typedef UserNotificationCallback = void Function(UserNotification, Either<Uint8List, FlowyError>);
+
+class UserNotificationParser extends NotificationParser<UserNotification, FlowyError> {
+  UserNotificationParser({required String id, required UserNotificationCallback callback})
+      : super(
+          id: id,
+          callback: callback,
+          tyParser: (ty) => UserNotification.valueOf(ty),
+          errorParser: (bytes) => FlowyError.fromBuffer(bytes),
+        );
+}
+
+typedef UserNotificationHandler = Function(UserNotification ty, Either<Uint8List, FlowyError> result);
+
+class UserNotificationListener {
+  StreamSubscription<SubscribeObject>? _subscription;
+  UserNotificationParser? _parser;
+
+  UserNotificationListener({required String objectId, required UserNotificationHandler handler})
+      : _parser = UserNotificationParser(id: objectId, callback: handler) {
+    _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
+  }
+
+  Future<void> stop() async {
+    _parser = null;
+    await _subscription?.cancel();
+  }
+}

+ 1 - 1
frontend/app_flowy/lib/plugin/plugin.dart

@@ -4,7 +4,7 @@ import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:flowy_infra/notifier.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/widgets.dart';
 
 export "./src/sandbox.dart";

+ 7 - 10
frontend/app_flowy/lib/startup/deps_resolver.dart

@@ -13,8 +13,8 @@ import 'package:app_flowy/user/application/prelude.dart';
 import 'package:app_flowy/user/presentation/router.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:fluttertoast/fluttertoast.dart';
 import 'package:get_it/get_it.dart';
@@ -52,7 +52,7 @@ void _resolveHomeDeps(GetIt getIt) {
   getIt.registerSingleton(MenuSharedState());
 
   getIt.registerFactoryParam<UserListener, UserProfile, void>(
-    (user, _) => UserListener(user: user),
+    (user, _) => UserListener(userProfile: user),
   );
 
   //
@@ -61,7 +61,7 @@ void _resolveHomeDeps(GetIt getIt) {
   getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
     (user, _) => WelcomeBloc(
       userService: UserService(userId: user.id),
-      userListener: getIt<UserListener>(param1: user),
+      userWorkspaceListener: UserWorkspaceListener(userProfile: user),
     ),
   );
 
@@ -73,8 +73,8 @@ void _resolveHomeDeps(GetIt getIt) {
 
 void _resolveFolderDeps(GetIt getIt) {
   //workspace
-  getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>((user, workspaceId) =>
-      WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId)));
+  getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>(
+      (user, workspaceId) => WorkspaceListener(user: user, workspaceId: workspaceId));
 
   // View
   getIt.registerFactoryParam<ViewListener, View, void>(
@@ -98,10 +98,7 @@ void _resolveFolderDeps(GetIt getIt) {
   );
 
   getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
-    (user, _) => MenuUserBloc(
-      user,
-      getIt<UserListener>(param1: user),
-    ),
+    (user, _) => MenuUserBloc(user),
   );
 
   // App

+ 91 - 58
frontend/app_flowy/lib/user/application/user_listener.dart

@@ -1,10 +1,11 @@
 import 'dart:async';
+import 'package:app_flowy/core/folder_notification.dart';
+import 'package:app_flowy/core/user_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-error-code/code.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'dart:typed_data';
-import 'package:app_flowy/core/notification_helper.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
@@ -14,108 +15,140 @@ import 'package:flowy_sdk/rust_stream.dart';
 
 typedef UserProfileNotifyValue = Either<UserProfile, FlowyError>;
 typedef AuthNotifyValue = Either<Unit, FlowyError>;
-typedef WorkspaceListNotifyValue = Either<List<Workspace>, FlowyError>;
-typedef WorkspaceSettingNotifyValue = Either<CurrentWorkspaceSetting, FlowyError>;
 
 class UserListener {
   StreamSubscription<SubscribeObject>? _subscription;
-  final _profileNotifier = PublishNotifier<UserProfileNotifyValue>();
-  final _authNotifier = PublishNotifier<AuthNotifyValue>();
-  final _workspaceListNotifier = PublishNotifier<WorkspaceListNotifyValue>();
-  final _workSettingNotifier = PublishNotifier<WorkspaceSettingNotifyValue>();
+  PublishNotifier<AuthNotifyValue>? _authNotifier = PublishNotifier();
+  PublishNotifier<UserProfileNotifyValue>? _profileNotifier = PublishNotifier();
 
-  FolderNotificationParser? _workspaceParser;
   UserNotificationParser? _userParser;
-  final UserProfile _user;
+  final UserProfile _userProfile;
   UserListener({
-    required UserProfile user,
-  }) : _user = user;
+    required UserProfile userProfile,
+  }) : _userProfile = userProfile;
 
   void start({
     void Function(AuthNotifyValue)? onAuthChanged,
     void Function(UserProfileNotifyValue)? onProfileUpdated,
-    void Function(WorkspaceListNotifyValue)? onWorkspaceListUpdated,
-    void Function(WorkspaceSettingNotifyValue)? onWorkspaceSettingUpdated,
   }) {
-    if (onAuthChanged != null) {
-      _authNotifier.addListener(() {
-        onAuthChanged(_authNotifier.currentValue!);
-      });
-    }
-
     if (onProfileUpdated != null) {
-      _profileNotifier.addListener(() {
-        onProfileUpdated(_profileNotifier.currentValue!);
-      });
-    }
-
-    if (onWorkspaceListUpdated != null) {
-      _workspaceListNotifier.addListener(() {
-        onWorkspaceListUpdated(_workspaceListNotifier.currentValue!);
-      });
+      _profileNotifier?.addPublishListener(onProfileUpdated);
     }
 
-    if (onWorkspaceSettingUpdated != null) {
-      _workSettingNotifier.addListener(() {
-        onWorkspaceSettingUpdated(_workSettingNotifier.currentValue!);
-      });
+    if (onAuthChanged != null) {
+      _authNotifier?.addPublishListener(onAuthChanged);
     }
 
-    _workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback);
-    _userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback);
+    _userParser = UserNotificationParser(id: _userProfile.token, callback: _userNotificationCallback);
     _subscription = RustStreamReceiver.listen((observable) {
-      _workspaceParser?.parse(observable);
       _userParser?.parse(observable);
     });
   }
 
   Future<void> stop() async {
-    _workspaceParser = null;
     _userParser = null;
     await _subscription?.cancel();
-    _profileNotifier.dispose();
-    _authNotifier.dispose();
-    _workspaceListNotifier.dispose();
+    _profileNotifier?.dispose();
+    _profileNotifier = null;
+
+    _authNotifier?.dispose();
+    _authNotifier = null;
+  }
+
+  void _userNotificationCallback(user.UserNotification ty, Either<Uint8List, FlowyError> result) {
+    switch (ty) {
+      case user.UserNotification.UserUnauthorized:
+        result.fold(
+          (_) {},
+          (error) => _authNotifier?.value = right(error),
+        );
+        break;
+      case user.UserNotification.UserProfileUpdated:
+        result.fold(
+          (payload) => _profileNotifier?.value = left(UserProfile.fromBuffer(payload)),
+          (error) => _profileNotifier?.value = right(error),
+        );
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+typedef WorkspaceListNotifyValue = Either<List<Workspace>, FlowyError>;
+typedef WorkspaceSettingNotifyValue = Either<CurrentWorkspaceSetting, FlowyError>;
+
+class UserWorkspaceListener {
+  PublishNotifier<AuthNotifyValue>? _authNotifier = PublishNotifier();
+  PublishNotifier<WorkspaceListNotifyValue>? _workspacesChangedNotifier = PublishNotifier();
+  PublishNotifier<WorkspaceSettingNotifyValue>? _settingChangedNotifier = PublishNotifier();
+
+  FolderNotificationListener? _listener;
+  final UserProfile _userProfile;
+
+  UserWorkspaceListener({
+    required UserProfile userProfile,
+  }) : _userProfile = userProfile;
+
+  void start({
+    void Function(AuthNotifyValue)? onAuthChanged,
+    void Function(WorkspaceListNotifyValue)? onWorkspacesUpdated,
+    void Function(WorkspaceSettingNotifyValue)? onSettingUpdated,
+  }) {
+    if (onAuthChanged != null) {
+      _authNotifier?.addPublishListener(onAuthChanged);
+    }
+
+    if (onWorkspacesUpdated != null) {
+      _workspacesChangedNotifier?.addPublishListener(onWorkspacesUpdated);
+    }
+
+    if (onSettingUpdated != null) {
+      _settingChangedNotifier?.addPublishListener(onSettingUpdated);
+    }
+
+    _listener = FolderNotificationListener(
+      objectId: _userProfile.token,
+      handler: _handleObservableType,
+    );
   }
 
-  void _notificationCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
+  void _handleObservableType(FolderNotification ty, Either<Uint8List, FlowyError> result) {
     switch (ty) {
       case FolderNotification.UserCreateWorkspace:
       case FolderNotification.UserDeleteWorkspace:
       case FolderNotification.WorkspaceListUpdated:
         result.fold(
-          (payload) => _workspaceListNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items),
-          (error) => _workspaceListNotifier.value = right(error),
+          (payload) => _workspacesChangedNotifier?.value = left(RepeatedWorkspace.fromBuffer(payload).items),
+          (error) => _workspacesChangedNotifier?.value = right(error),
         );
         break;
       case FolderNotification.WorkspaceSetting:
         result.fold(
-          (payload) => _workSettingNotifier.value = left(CurrentWorkspaceSetting.fromBuffer(payload)),
-          (error) => _workSettingNotifier.value = right(error),
+          (payload) => _settingChangedNotifier?.value = left(CurrentWorkspaceSetting.fromBuffer(payload)),
+          (error) => _settingChangedNotifier?.value = right(error),
         );
         break;
       case FolderNotification.UserUnauthorized:
         result.fold(
           (_) {},
-          (error) => _authNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
+          (error) => _authNotifier?.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
         );
         break;
-
       default:
         break;
     }
   }
 
-  void _userNotificationCallback(user.UserNotification ty, Either<Uint8List, FlowyError> result) {
-    switch (ty) {
-      case user.UserNotification.UserUnauthorized:
-        result.fold(
-          (payload) => _profileNotifier.value = left(UserProfile.fromBuffer(payload)),
-          (error) => _profileNotifier.value = right(error),
-        );
-        break;
-      default:
-        break;
-    }
+  Future<void> stop() async {
+    await _listener?.stop();
+    _workspacesChangedNotifier?.dispose();
+    _workspacesChangedNotifier = null;
+
+    _settingChangedNotifier?.dispose();
+    _settingChangedNotifier = null;
+
+    _authNotifier?.dispose();
+    _authNotifier = null;
   }
 }

+ 1 - 1
frontend/app_flowy/lib/user/application/user_service.dart

@@ -3,7 +3,7 @@ import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 
 class UserService {

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

@@ -8,7 +8,7 @@ import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
 import 'package:flowy_infra/time/duration.dart';
 import 'package:flowy_infra_ui/widget/route/animation.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile;
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/protobuf.dart';
 import 'package:flutter/material.dart';
 
 class AuthRouter {

+ 1 - 4
frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart

@@ -1,5 +1,4 @@
 import 'package:app_flowy/user/application/auth_service.dart';
-import 'package:app_flowy/user/application/user_listener.dart';
 import 'package:app_flowy/user/presentation/router.dart';
 import 'package:app_flowy/user/presentation/widgets/background.dart';
 import 'package:easy_localization/easy_localization.dart';
@@ -10,7 +9,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:flutter/material.dart';
@@ -34,8 +33,6 @@ class SkipLogInScreen extends StatefulWidget {
 }
 
 class _SkipLogInScreenState extends State<SkipLogInScreen> {
-  UserListener? userListener;
-
   @override
   Widget build(BuildContext context) {
     return Scaffold(

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

@@ -5,7 +5,7 @@ import 'package:flowy_infra/theme.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:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 2 - 2
frontend/app_flowy/lib/workspace/application/app/app_bloc.dart

@@ -7,8 +7,8 @@ import 'package:app_flowy/workspace/application/app/app_service.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
 import 'package:expandable/expandable.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 3 - 3
frontend/app_flowy/lib/workspace/application/app/app_listener.dart

@@ -1,12 +1,12 @@
 import 'dart:async';
 import 'dart:typed_data';
+import 'package:app_flowy/core/folder_notification.dart';
 import 'package:dartz/dartz.dart';
-import 'package:app_flowy/core/notification_helper.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
 import 'package:flowy_sdk/rust_stream.dart';
 

+ 2 - 2
frontend/app_flowy/lib/workspace/application/app/app_service.dart

@@ -3,8 +3,8 @@ import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 
 import 'package:app_flowy/plugin/plugin.dart';
 

+ 2 - 2
frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart

@@ -2,9 +2,9 @@ import 'dart:convert';
 import 'package:app_flowy/workspace/application/doc/doc_service.dart';
 import 'package:app_flowy/workspace/application/trash/trash_service.dart';
 import 'package:app_flowy/workspace/application/view/view_listener.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter_quill/flutter_quill.dart' show Document, Delta;
 import 'package:flowy_sdk/log.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/doc/doc_service.dart

@@ -1,7 +1,7 @@
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-sync/text_block.pb.dart';
 

+ 1 - 1
frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart

@@ -4,7 +4,7 @@ import 'package:app_flowy/startup/tasks/rust_sdk.dart';
 import 'package:app_flowy/workspace/application/doc/share_service.dart';
 import 'package:app_flowy/workspace/application/markdown/delta_markdown.dart';
 import 'package:flowy_sdk/protobuf/flowy-text-block/entities.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 1 - 2
frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart

@@ -1,7 +1,6 @@
 import 'dart:async';
 import 'dart:typed_data';
-
-import 'package:app_flowy/core/notification_helper.dart';
+import 'package:app_flowy/core/grid_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/cell/cell_listener.dart

@@ -1,10 +1,10 @@
+import 'package:app_flowy/core/grid_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'dart:async';
 import 'dart:typed_data';
-import 'package:app_flowy/core/notification_helper.dart';
 
 typedef UpdateFieldNotifiedValue = Either<Unit, FlowyError>;
 

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart

@@ -1,10 +1,10 @@
+import 'package:app_flowy/core/grid_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'dart:async';
 import 'dart:typed_data';
-import 'package:app_flowy/core/notification_helper.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 
 typedef UpdateFieldNotifiedValue = Either<Field, FlowyError>;

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart

@@ -1,10 +1,10 @@
+import 'package:app_flowy/core/grid_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'dart:async';
 import 'dart:typed_data';
-import 'package:app_flowy/core/notification_helper.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 
 typedef UpdateFieldNotifiedValue = Either<GridFieldChangeset, FlowyError>;

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart

@@ -3,7 +3,7 @@ import 'package:dartz/dartz.dart';
 import 'package:equatable/equatable.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/grid_service.dart

@@ -5,7 +5,7 @@ import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart

@@ -1,10 +1,10 @@
+import 'package:app_flowy/core/grid_notification.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'dart:async';
 import 'dart:typed_data';
-import 'package:app_flowy/core/notification_helper.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 

+ 5 - 7
frontend/app_flowy/lib/workspace/application/home/home_bloc.dart

@@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error-code/code.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart' show CurrentWorkspaceSetting;
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart' show CurrentWorkspaceSetting;
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -11,19 +11,17 @@ import 'package:dartz/dartz.dart';
 part 'home_bloc.freezed.dart';
 
 class HomeBloc extends Bloc<HomeEvent, HomeState> {
-  final UserListener _listener;
+  final UserWorkspaceListener _listener;
 
   HomeBloc(UserProfile user, CurrentWorkspaceSetting workspaceSetting)
-      : _listener = UserListener(user: user),
+      : _listener = UserWorkspaceListener(userProfile: user),
         super(HomeState.initial(workspaceSetting)) {
     on<HomeEvent>((event, emit) async {
       await event.map(
         initial: (_Initial value) {
           _listener.start(
-            onAuthChanged: (result) {
-              _authDidChanged(result);
-            },
-            onWorkspaceSettingUpdated: (result) {
+            onAuthChanged: (result) => _authDidChanged(result),
+            onSettingUpdated: (result) {
               result.fold(
                 (setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)),
                 (r) => Log.error(r),

+ 2 - 2
frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart

@@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/application/workspace/workspace_listener.dar
 import 'package:app_flowy/workspace/application/workspace/workspace_service.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -22,7 +22,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
     on<MenuEvent>((event, emit) async {
       await event.map(
         initial: (e) async {
-          listener.start(addAppCallback: _handleAppsOrFail);
+          listener.start(appsChanged: _handleAppsOrFail);
           await _fetchApps(emit);
         },
         openPage: (e) async {

+ 40 - 27
frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:app_flowy/user/application/user_listener.dart';
 import 'package:app_flowy/user/application/user_service.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -12,29 +12,44 @@ part 'menu_user_bloc.freezed.dart';
 
 class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
   final UserService _userService;
-  final UserListener userListener;
+  final UserListener _userListener;
+  final UserWorkspaceListener _userWorkspaceListener;
   final UserProfile userProfile;
 
-  MenuUserBloc(this.userProfile, this.userListener)
-      : _userService = UserService(userId: userProfile.id),
+  MenuUserBloc(this.userProfile)
+      : _userListener = UserListener(userProfile: userProfile),
+        _userWorkspaceListener = UserWorkspaceListener(userProfile: userProfile),
+        _userService = UserService(userId: userProfile.id),
         super(MenuUserState.initial(userProfile)) {
     on<MenuUserEvent>((event, emit) async {
-      await event.map(
-        initial: (_) async {
-          userListener.start(
-            onProfileUpdated: _profileUpdated,
-            onWorkspaceListUpdated: _workspaceListUpdated,
-          );
+      await event.when(
+        initial: () async {
+          _userListener.start(onProfileUpdated: _profileUpdated);
+          _userWorkspaceListener.start(onWorkspacesUpdated: _workspaceListUpdated);
           await _initUser();
         },
-        fetchWorkspaces: (_FetchWorkspaces value) async {},
+        fetchWorkspaces: () async {
+          //
+        },
+        didReceiveUserProfile: (UserProfile newUserProfile) {
+          emit(state.copyWith(userProfile: newUserProfile));
+        },
+        updateUserName: (String name) {
+          _userService.updateUserProfile(name: name).then((result) {
+            result.fold(
+              (l) => null,
+              (err) => Log.error(err),
+            );
+          });
+        },
       );
     });
   }
 
   @override
   Future<void> close() async {
-    await userListener.stop();
+    await _userListener.stop();
+    await _userWorkspaceListener.stop();
     super.close();
   }
 
@@ -43,19 +58,15 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
     result.fold((l) => null, (error) => Log.error(error));
   }
 
-  void _profileUpdated(Either<UserProfile, FlowyError> userOrFailed) {}
+  void _profileUpdated(Either<UserProfile, FlowyError> userProfileOrFailed) {
+    userProfileOrFailed.fold(
+      (newUserProfile) => add(MenuUserEvent.didReceiveUserProfile(newUserProfile)),
+      (err) => Log.error(err),
+    );
+  }
+
   void _workspaceListUpdated(Either<List<Workspace>, FlowyError> workspacesOrFailed) {
-    // fetch workspaces
-    // iUserImpl.fetchWorkspaces().then((result) {
-    //   result.fold(
-    //     (workspaces) async* {
-    //       yield state.copyWith(workspaces: some(workspaces));
-    //     },
-    //     (error) async* {
-    //       yield state.copyWith(successOrFailure: right(error.msg));
-    //     },
-    //   );
-    // });
+    // Do nothing by now
   }
 }
 
@@ -63,18 +74,20 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
 class MenuUserEvent with _$MenuUserEvent {
   const factory MenuUserEvent.initial() = _Initial;
   const factory MenuUserEvent.fetchWorkspaces() = _FetchWorkspaces;
+  const factory MenuUserEvent.updateUserName(String name) = _UpdateUserName;
+  const factory MenuUserEvent.didReceiveUserProfile(UserProfile newUserProfile) = _DidReceiveUserProfile;
 }
 
 @freezed
 class MenuUserState with _$MenuUserState {
   const factory MenuUserState({
-    required UserProfile user,
+    required UserProfile userProfile,
     required Option<List<Workspace>> workspaces,
     required Either<Unit, String> successOrFailure,
   }) = _MenuUserState;
 
-  factory MenuUserState.initial(UserProfile user) => MenuUserState(
-        user: user,
+  factory MenuUserState.initial(UserProfile userProfile) => MenuUserState(
+        userProfile: userProfile,
         workspaces: none(),
         successOrFailure: left(unit),
       );

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

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

+ 1 - 1
frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart

@@ -1,6 +1,6 @@
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 2 - 2
frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart

@@ -1,11 +1,11 @@
 import 'dart:async';
 import 'dart:typed_data';
+import 'package:app_flowy/core/folder_notification.dart';
 import 'package:dartz/dartz.dart';
-import 'package:app_flowy/core/notification_helper.dart';
 import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
 import 'package:flowy_sdk/rust_stream.dart';
 
 typedef TrashUpdatedCallback = void Function(Either<List<Trash>, FlowyError> trashOrFailed);

+ 1 - 2
frontend/app_flowy/lib/workspace/application/trash/trash_service.dart

@@ -2,7 +2,7 @@ import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
 
 class TrashService {
   Future<Either<RepeatedTrash, FlowyError>> readTrash() {
@@ -34,4 +34,3 @@ class TrashService {
     return FolderEventDeleteAllTrash().send();
   }
 }
-

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

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

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

@@ -1,6 +1,6 @@
 import 'package:app_flowy/plugin/plugin.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 
 enum FlowyPlugin {

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

@@ -1,9 +1,9 @@
 import 'dart:async';
 import 'dart:typed_data';
-import 'package:app_flowy/core/notification_helper.dart';
+import 'package:app_flowy/core/folder_notification.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
 import 'package:flowy_sdk/rust_stream.dart';

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

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

+ 6 - 6
frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:app_flowy/user/application/user_listener.dart';
 import 'package:app_flowy/user/application/user_service.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -11,13 +11,13 @@ part 'welcome_bloc.freezed.dart';
 
 class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
   final UserService userService;
-  final UserListener userListener;
-  WelcomeBloc({required this.userService, required this.userListener}) : super(WelcomeState.initial()) {
+  final UserWorkspaceListener userWorkspaceListener;
+  WelcomeBloc({required this.userService, required this.userWorkspaceListener}) : super(WelcomeState.initial()) {
     on<WelcomeEvent>(
       (event, emit) async {
         await event.map(initial: (e) async {
-          userListener.start(
-            onWorkspaceListUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)),
+          userWorkspaceListener.start(
+            onWorkspacesUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)),
           );
           //
           await _fetchWorkspaces(emit);
@@ -37,7 +37,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
 
   @override
   Future<void> close() async {
-    await userListener.stop();
+    await userWorkspaceListener.stop();
     super.close();
   }
 

+ 38 - 62
frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart

@@ -1,97 +1,73 @@
 import 'dart:async';
 import 'dart:typed_data';
-
-import 'package:app_flowy/core/notification_helper.dart';
+import 'package:app_flowy/core/folder_notification.dart';
 import 'package:dartz/dartz.dart';
-import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
+import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile;
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
-import 'package:flowy_sdk/rust_stream.dart';
 
-typedef WorkspaceAppsChangedCallback = void Function(Either<List<App>, FlowyError> appsOrFail);
-typedef WorkspaceUpdatedCallback = void Function(String name, String desc);
+typedef AppListNotifyValue = Either<List<App>, FlowyError>;
+typedef WorkspaceNotifyValue = Either<Workspace, FlowyError>;
 
 class WorkspaceListener {
-  WorkspaceListenerService service;
-  WorkspaceListener({
-    required this.service,
-  });
-
-  void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback}) {
-    service.startListening(appsChanged: addAppCallback, update: updatedCallback);
-  }
-
-  Future<void> stop() async {
-    await service.close();
-  }
-}
+  PublishNotifier<AppListNotifyValue>? _appsChangedNotifier = PublishNotifier();
+  PublishNotifier<WorkspaceNotifyValue>? _workspaceUpdatedNotifier = PublishNotifier();
 
-class WorkspaceListenerService {
-  StreamSubscription<SubscribeObject>? _subscription;
-  WorkspaceAppsChangedCallback? _appsChanged;
-  WorkspaceUpdatedCallback? _update;
-  FolderNotificationParser? _parser;
+  FolderNotificationListener? _listener;
   final UserProfile user;
   final String workspaceId;
 
-  WorkspaceListenerService({
+  WorkspaceListener({
     required this.user,
     required this.workspaceId,
   });
 
-  void startListening({
-    WorkspaceAppsChangedCallback? appsChanged,
-    WorkspaceUpdatedCallback? update,
+  void start({
+    void Function(AppListNotifyValue)? appsChanged,
+    void Function(WorkspaceNotifyValue)? onWorkspaceUpdated,
   }) {
-    _appsChanged = appsChanged;
-    _update = update;
+    if (appsChanged != null) {
+      _appsChangedNotifier?.addPublishListener(appsChanged);
+    }
 
-    _parser = FolderNotificationParser(
-      id: workspaceId,
-      callback: (ty, result) {
-        _handleObservableType(ty, result);
-      },
-    );
+    if (onWorkspaceUpdated != null) {
+      _workspaceUpdatedNotifier?.addPublishListener(onWorkspaceUpdated);
+    }
 
-    _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
+    _listener = FolderNotificationListener(
+      objectId: workspaceId,
+      handler: _handleObservableType,
+    );
   }
 
   void _handleObservableType(FolderNotification ty, Either<Uint8List, FlowyError> result) {
     switch (ty) {
       case FolderNotification.WorkspaceUpdated:
-        if (_update != null) {
-          result.fold(
-            (payload) {
-              final workspace = Workspace.fromBuffer(payload);
-              _update!(workspace.name, workspace.desc);
-            },
-            (error) => Log.error(error),
-          );
-        }
+        result.fold(
+          (payload) => _workspaceUpdatedNotifier?.value = left(Workspace.fromBuffer(payload)),
+          (error) => _workspaceUpdatedNotifier?.value = right(error),
+        );
         break;
       case FolderNotification.WorkspaceAppsChanged:
-        if (_appsChanged != null) {
-          result.fold(
-            (payload) => _appsChanged!(
-              left(RepeatedApp.fromBuffer(payload).items),
-            ),
-            (error) => _appsChanged!(right(error)),
-          );
-        }
+        result.fold(
+          (payload) => _appsChangedNotifier?.value = left(RepeatedApp.fromBuffer(payload).items),
+          (error) => _appsChangedNotifier?.value = right(error),
+        );
         break;
       default:
         break;
     }
   }
 
-  Future<void> close() async {
-    _parser = null;
-    await _subscription?.cancel();
-    // _appsChanged = null;
-    // _update = null;
+  Future<void> stop() async {
+    await _listener?.stop();
+    _appsChangedNotifier?.dispose();
+    _appsChangedNotifier = null;
+
+    _workspaceUpdatedNotifier?.dispose();
+    _workspaceUpdatedNotifier = null;
   }
 }

+ 3 - 3
frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart

@@ -4,9 +4,9 @@ import 'package:dartz/dartz.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart' show MoveFolderItemPayload, MoveFolderItemType;
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart' show MoveFolderItemPayload, MoveFolderItemType;
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 
 import 'package:app_flowy/generated/locale_keys.g.dart';
 

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart

@@ -6,7 +6,7 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_infra_ui/style_widget/container.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile;
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/protobuf.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';

+ 1 - 0
frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart

@@ -83,6 +83,7 @@ class CreateItem extends StatelessWidget {
     return FlowyHover(
       style: config,
       child: GestureDetector(
+        behavior: HitTestBehavior.opaque,
         onTap: () => onSelected(pluginBuilder),
         child: FlowyText.medium(
           pluginBuilder.menuName,

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart

@@ -5,7 +5,7 @@ import 'package:flowy_infra/icon_data.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:app_flowy/workspace/application/app/app_bloc.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart

@@ -1,7 +1,7 @@
 import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
 import 'package:expandable/expandable.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:app_flowy/startup/startup.dart';

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

@@ -9,7 +9,7 @@ import 'package:flowy_infra/theme.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:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart

@@ -11,8 +11,8 @@ import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile;
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart

@@ -58,9 +58,9 @@ class MenuUser extends StatelessWidget {
   }
 
   Widget _renderUserName(BuildContext context) {
-    String name = context.read<MenuUserBloc>().state.user.name;
+    String name = context.read<MenuUserBloc>().state.userProfile.name;
     if (name.isEmpty) {
-      name = context.read<MenuUserBloc>().state.user.email;
+      name = context.read<MenuUserBloc>().state.userProfile.email;
     }
     return FlowyText(name, fontSize: 12);
   }

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/board/board.dart

@@ -1,6 +1,6 @@
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/plugins/widgets/left_bar_item.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:app_flowy/plugin/plugin.dart';
 import 'package:flutter/material.dart';
 

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/board/src/board_page.dart

@@ -1,6 +1,6 @@
 // ignore_for_file: unused_field
 
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 
 class BoardPage extends StatelessWidget {

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart

@@ -20,7 +20,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-text-block/entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart

@@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter_quill/flutter_quill.dart' as quill;
 import 'package:flowy_infra_ui/widget/error_page.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:provider/provider.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart

@@ -3,7 +3,7 @@ import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/plugins/widgets/left_bar_item.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 
 import 'src/grid_page.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart

@@ -5,7 +5,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 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/widget/error_page.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 import 'package:linked_scroll_controller/linked_scroll_controller.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart

@@ -3,7 +3,7 @@ import 'package:flowy_infra/theme.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:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:intl/intl.dart';
 import 'package:fixnum/fixnum.dart' as $fixnum;

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

@@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/application/view/view_listener.dart';
 import 'package:app_flowy/workspace/application/view/view_service.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 1 - 0
frontend/app_flowy/macos/Runner.xcodeproj/project.pbxproj

@@ -427,6 +427,7 @@
 					"$(inherited)",
 					"@executable_path/../Frameworks",
 				);
+				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = com.appflowy.macos;
 				PRODUCT_NAME = AppFlowy;
 				PROVISIONING_PROFILE_SPECIFIER = "";

+ 1 - 2
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart

@@ -6,7 +6,6 @@ import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/event_map.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder/event_map.pb.dart';
 import 'package:isolates/isolates.dart';
 import 'package:isolates/ports.dart';
 import 'package:ffi/ffi.dart';
@@ -17,7 +16,7 @@ import 'dart:typed_data';
 import 'package:flowy_sdk/ffi.dart' as ffi;
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart';
 import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-text-block/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-sync/protobuf.dart';

+ 1 - 0
frontend/rust-lib/Cargo.lock

@@ -904,6 +904,7 @@ dependencies = [
  "strum_macros",
  "tokio",
  "tracing",
+ "unicode-segmentation",
 ]
 
 [[package]]

+ 1 - 0
frontend/rust-lib/flowy-folder/Cargo.toml

@@ -34,6 +34,7 @@ serde = { version = "1.0", features = ["derive"] }
 tracing = { version = "0.1", features = ["log"] }
 bytes = { version = "1.0" }
 
+unicode-segmentation = "1.8"
 [dev-dependencies]
 serde_json = "1.0"
 flowy-folder = { path = "../flowy-folder", features = ["flowy_unit_test"]}

+ 25 - 9
shared-lib/flowy-folder-data-model/src/entities/app.rs → frontend/rust-lib/flowy-folder/src/entities/app.rs

@@ -1,20 +1,16 @@
 use crate::{
-    entities::view::RepeatedView,
-    errors::ErrorCode,
-    impl_def_and_def_mut,
-    parser::{
+    entities::parser::{
         app::{AppColorStyle, AppIdentify, AppName},
         workspace::WorkspaceIdentify,
     },
+    entities::view::RepeatedView,
+    errors::ErrorCode,
+    impl_def_and_def_mut,
 };
 use flowy_derive::ProtoBuf;
-use nanoid::nanoid;
-
+use flowy_folder_data_model::revision::AppRevision;
 use std::convert::TryInto;
 
-pub fn gen_app_id() -> String {
-    nanoid!(10)
-}
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
 pub struct App {
     #[pb(index = 1)]
@@ -42,6 +38,20 @@ pub struct App {
     pub create_time: i64,
 }
 
+impl std::convert::From<AppRevision> for App {
+    fn from(app_serde: AppRevision) -> Self {
+        App {
+            id: app_serde.id,
+            workspace_id: app_serde.workspace_id,
+            name: app_serde.name,
+            desc: app_serde.desc,
+            belongings: app_serde.belongings.into(),
+            version: app_serde.version,
+            modified_time: app_serde.modified_time,
+            create_time: app_serde.create_time,
+        }
+    }
+}
 #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)]
 pub struct RepeatedApp {
     #[pb(index = 1)]
@@ -50,6 +60,12 @@ pub struct RepeatedApp {
 
 impl_def_and_def_mut!(RepeatedApp, App);
 
+impl std::convert::From<Vec<AppRevision>> for RepeatedApp {
+    fn from(values: Vec<AppRevision>) -> Self {
+        let items = values.into_iter().map(|value| value.into()).collect::<Vec<App>>();
+        RepeatedApp { items }
+    }
+}
 #[derive(ProtoBuf, Default)]
 pub struct CreateAppPayload {
     #[pb(index = 1)]

+ 1 - 0
shared-lib/flowy-folder-data-model/src/entities/mod.rs → frontend/rust-lib/flowy-folder/src/entities/mod.rs

@@ -1,4 +1,5 @@
 pub mod app;
+mod parser;
 pub mod trash;
 pub mod view;
 mod view_info;

+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/app/app_color_style.rs → frontend/rust-lib/flowy-folder/src/entities/parser/app/app_color_style.rs


+ 1 - 0
shared-lib/flowy-folder-data-model/src/parser/app/app_desc.rs → frontend/rust-lib/flowy-folder/src/entities/parser/app/app_desc.rs

@@ -3,6 +3,7 @@ use unicode_segmentation::UnicodeSegmentation;
 pub struct AppDesc(pub String);
 
 impl AppDesc {
+    #[allow(dead_code)]
     pub fn parse(s: String) -> Result<AppDesc, String> {
         if s.graphemes(true).count() > 1024 {
             return Err("Workspace description too long".to_string());

+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/app/app_id.rs → frontend/rust-lib/flowy-folder/src/entities/parser/app/app_id.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/app/app_name.rs → frontend/rust-lib/flowy-folder/src/entities/parser/app/app_name.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/app/mod.rs → frontend/rust-lib/flowy-folder/src/entities/parser/app/mod.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/mod.rs → frontend/rust-lib/flowy-folder/src/entities/parser/mod.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/trash/mod.rs → frontend/rust-lib/flowy-folder/src/entities/parser/trash/mod.rs


+ 2 - 0
shared-lib/flowy-folder-data-model/src/parser/trash/trash_id.rs → frontend/rust-lib/flowy-folder/src/entities/parser/trash/trash_id.rs

@@ -2,6 +2,7 @@
 pub struct TrashIdentify(pub String);
 
 impl TrashIdentify {
+    #[allow(dead_code)]
     pub fn parse(s: String) -> Result<TrashIdentify, String> {
         if s.trim().is_empty() {
             return Err("Trash id can not be empty or whitespace".to_string());
@@ -21,6 +22,7 @@ impl AsRef<str> for TrashIdentify {
 pub struct TrashIds(pub Vec<String>);
 
 impl TrashIds {
+    #[allow(dead_code)]
     pub fn parse(ids: Vec<String>) -> Result<TrashIds, String> {
         let mut trash_ids = vec![];
         for id in ids {

+ 0 - 4
shared-lib/flowy-folder-data-model/src/parser/view/mod.rs → frontend/rust-lib/flowy-folder/src/entities/parser/view/mod.rs

@@ -1,13 +1,9 @@
-mod delta_data;
 mod view_desc;
-mod view_ext;
 mod view_id;
 mod view_name;
 mod view_thumbnail;
 
-pub use delta_data::*;
 pub use view_desc::*;
-pub use view_ext::*;
 pub use view_id::*;
 pub use view_name::*;
 pub use view_thumbnail::*;

+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/view/view_desc.rs → frontend/rust-lib/flowy-folder/src/entities/parser/view/view_desc.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/view/view_id.rs → frontend/rust-lib/flowy-folder/src/entities/parser/view/view_id.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/view/view_name.rs → frontend/rust-lib/flowy-folder/src/entities/parser/view/view_name.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/view/view_thumbnail.rs → frontend/rust-lib/flowy-folder/src/entities/parser/view/view_thumbnail.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/workspace/mod.rs → frontend/rust-lib/flowy-folder/src/entities/parser/workspace/mod.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/workspace/workspace_desc.rs → frontend/rust-lib/flowy-folder/src/entities/parser/workspace/workspace_desc.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/workspace/workspace_id.rs → frontend/rust-lib/flowy-folder/src/entities/parser/workspace/workspace_id.rs


+ 0 - 0
shared-lib/flowy-folder-data-model/src/parser/workspace/workspace_name.rs → frontend/rust-lib/flowy-folder/src/entities/parser/workspace/workspace_name.rs


+ 66 - 5
shared-lib/flowy-folder-data-model/src/entities/trash.rs → frontend/rust-lib/flowy-folder/src/entities/trash.rs

@@ -1,6 +1,6 @@
 use crate::impl_def_and_def_mut;
-use crate::revision::TrashRevision;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
+use flowy_folder_data_model::revision::{TrashRevision, TrashTypeRevision};
 use serde::{Deserialize, Serialize};
 use std::fmt::Formatter;
 
@@ -22,6 +22,29 @@ pub struct Trash {
     pub ty: TrashType,
 }
 
+impl std::convert::From<TrashRevision> for Trash {
+    fn from(trash_rev: TrashRevision) -> Self {
+        Trash {
+            id: trash_rev.id,
+            name: trash_rev.name,
+            modified_time: trash_rev.modified_time,
+            create_time: trash_rev.create_time,
+            ty: trash_rev.ty.into(),
+        }
+    }
+}
+
+impl std::convert::From<Trash> for TrashRevision {
+    fn from(trash: Trash) -> Self {
+        TrashRevision {
+            id: trash.id,
+            name: trash.name,
+            modified_time: trash.modified_time,
+            create_time: trash.create_time,
+            ty: trash.ty.into(),
+        }
+    }
+}
 #[derive(PartialEq, Debug, Default, ProtoBuf, Clone)]
 pub struct RepeatedTrash {
     #[pb(index = 1)]
@@ -29,10 +52,16 @@ pub struct RepeatedTrash {
 }
 
 impl_def_and_def_mut!(RepeatedTrash, Trash);
+impl std::convert::From<Vec<TrashRevision>> for RepeatedTrash {
+    fn from(trash_revs: Vec<TrashRevision>) -> Self {
+        let items: Vec<Trash> = trash_revs.into_iter().map(|trash_rev| trash_rev.into()).collect();
+        RepeatedTrash { items }
+    }
+}
 
 #[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize, Deserialize)]
 pub enum TrashType {
-    Unknown = 0,
+    TrashUnknown = 0,
     TrashView = 1,
     TrashApp = 2,
 }
@@ -42,7 +71,7 @@ impl std::convert::TryFrom<i32> for TrashType {
 
     fn try_from(value: i32) -> Result<Self, Self::Error> {
         match value {
-            0 => Ok(TrashType::Unknown),
+            0 => Ok(TrashType::TrashUnknown),
             1 => Ok(TrashType::TrashView),
             2 => Ok(TrashType::TrashApp),
             _ => Err(format!("Invalid trash type: {}", value)),
@@ -50,9 +79,29 @@ impl std::convert::TryFrom<i32> for TrashType {
     }
 }
 
+impl std::convert::From<TrashTypeRevision> for TrashType {
+    fn from(rev: TrashTypeRevision) -> Self {
+        match rev {
+            TrashTypeRevision::Unknown => TrashType::TrashUnknown,
+            TrashTypeRevision::TrashView => TrashType::TrashView,
+            TrashTypeRevision::TrashApp => TrashType::TrashApp,
+        }
+    }
+}
+
+impl std::convert::From<TrashType> for TrashTypeRevision {
+    fn from(rev: TrashType) -> Self {
+        match rev {
+            TrashType::TrashUnknown => TrashTypeRevision::Unknown,
+            TrashType::TrashView => TrashTypeRevision::TrashView,
+            TrashType::TrashApp => TrashTypeRevision::TrashApp,
+        }
+    }
+}
+
 impl std::default::Default for TrashType {
     fn default() -> Self {
-        TrashType::Unknown
+        TrashType::TrashUnknown
     }
 }
 
@@ -96,7 +145,10 @@ impl std::convert::From<Vec<TrashRevision>> for RepeatedTrashId {
     fn from(trash: Vec<TrashRevision>) -> Self {
         let items = trash
             .into_iter()
-            .map(|t| TrashId { id: t.id, ty: t.ty })
+            .map(|t| TrashId {
+                id: t.id,
+                ty: t.ty.into(),
+            })
             .collect::<Vec<_>>();
 
         RepeatedTrashId {
@@ -120,3 +172,12 @@ impl std::fmt::Display for TrashId {
         f.write_str(&format!("{:?}:{}", self.ty, self.id))
     }
 }
+
+impl std::convert::From<&TrashRevision> for TrashId {
+    fn from(trash: &TrashRevision) -> Self {
+        TrashId {
+            id: trash.id.clone(),
+            ty: trash.ty.clone().into(),
+        }
+    }
+}

+ 40 - 21
shared-lib/flowy-folder-data-model/src/entities/view.rs → frontend/rust-lib/flowy-folder/src/entities/view.rs

@@ -1,20 +1,15 @@
 use crate::{
-    errors::ErrorCode,
-    impl_def_and_def_mut,
-    parser::{
+    entities::parser::{
         app::AppIdentify,
         view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail},
     },
+    errors::ErrorCode,
+    impl_def_and_def_mut,
 };
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use nanoid::nanoid;
-use serde_repr::*;
+use flowy_folder_data_model::revision::{gen_view_id, ViewDataTypeRevision, ViewRevision};
 use std::convert::TryInto;
 
-pub fn gen_view_id() -> String {
-    nanoid!(10)
-}
-
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
 pub struct View {
     #[pb(index = 1)]
@@ -39,8 +34,21 @@ pub struct View {
     pub plugin_type: i32,
 }
 
-#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone, Serialize_repr, Deserialize_repr)]
-#[repr(u8)]
+impl std::convert::From<ViewRevision> for View {
+    fn from(rev: ViewRevision) -> Self {
+        View {
+            id: rev.id,
+            belong_to_id: rev.belong_to_id,
+            name: rev.name,
+            data_type: rev.data_type.into(),
+            modified_time: rev.modified_time,
+            create_time: rev.create_time,
+            plugin_type: rev.plugin_type,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
 pub enum ViewDataType {
     TextBlock = 0,
     Grid = 1,
@@ -48,19 +56,24 @@ pub enum ViewDataType {
 
 impl std::default::Default for ViewDataType {
     fn default() -> Self {
-        ViewDataType::TextBlock
+        ViewDataTypeRevision::default().into()
+    }
+}
+
+impl std::convert::From<ViewDataTypeRevision> for ViewDataType {
+    fn from(rev: ViewDataTypeRevision) -> Self {
+        match rev {
+            ViewDataTypeRevision::TextBlock => ViewDataType::TextBlock,
+            ViewDataTypeRevision::Grid => ViewDataType::Grid,
+        }
     }
 }
 
-impl std::convert::From<i32> for ViewDataType {
-    fn from(val: i32) -> Self {
-        match val {
-            0 => ViewDataType::TextBlock,
-            1 => ViewDataType::Grid,
-            _ => {
-                log::error!("Invalid view type: {}", val);
-                ViewDataType::TextBlock
-            }
+impl std::convert::From<ViewDataType> for ViewDataTypeRevision {
+    fn from(ty: ViewDataType) -> Self {
+        match ty {
+            ViewDataType::TextBlock => ViewDataTypeRevision::TextBlock,
+            ViewDataType::Grid => ViewDataTypeRevision::Grid,
         }
     }
 }
@@ -73,6 +86,12 @@ pub struct RepeatedView {
 
 impl_def_and_def_mut!(RepeatedView, View);
 
+impl std::convert::From<Vec<ViewRevision>> for RepeatedView {
+    fn from(values: Vec<ViewRevision>) -> Self {
+        let items = values.into_iter().map(|value| value.into()).collect::<Vec<View>>();
+        RepeatedView { items }
+    }
+}
 #[derive(Default, ProtoBuf)]
 pub struct RepeatedViewId {
     #[pb(index = 1)]

+ 0 - 0
shared-lib/flowy-folder-data-model/src/entities/view_info.rs → frontend/rust-lib/flowy-folder/src/entities/view_info.rs


+ 14 - 6
shared-lib/flowy-folder-data-model/src/entities/workspace.rs → frontend/rust-lib/flowy-folder/src/entities/workspace.rs

@@ -1,17 +1,13 @@
 use crate::{
+    entities::parser::workspace::{WorkspaceDesc, WorkspaceIdentify, WorkspaceName},
     entities::{app::RepeatedApp, view::View},
     errors::*,
     impl_def_and_def_mut,
-    parser::workspace::{WorkspaceDesc, WorkspaceIdentify, WorkspaceName},
 };
 use flowy_derive::ProtoBuf;
-use nanoid::nanoid;
-
+use flowy_folder_data_model::revision::WorkspaceRevision;
 use std::convert::TryInto;
 
-pub fn gen_workspace_id() -> String {
-    nanoid!(10)
-}
 #[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]
 pub struct Workspace {
     #[pb(index = 1)]
@@ -33,6 +29,18 @@ pub struct Workspace {
     pub create_time: i64,
 }
 
+impl std::convert::From<WorkspaceRevision> for Workspace {
+    fn from(workspace_serde: WorkspaceRevision) -> Self {
+        Workspace {
+            id: workspace_serde.id,
+            name: workspace_serde.name,
+            desc: workspace_serde.desc,
+            apps: workspace_serde.apps.into(),
+            modified_time: workspace_serde.modified_time,
+            create_time: workspace_serde.create_time,
+        }
+    }
+}
 #[derive(PartialEq, Debug, Default, ProtoBuf)]
 pub struct RepeatedWorkspace {
     #[pb(index = 1)]

+ 1 - 3
frontend/rust-lib/flowy-folder/src/lib.rs

@@ -1,4 +1,4 @@
-pub use flowy_folder_data_model::entities;
+pub mod entities;
 pub mod event_map;
 pub mod services;
 
@@ -14,8 +14,6 @@ pub mod protobuf;
 mod util;
 
 pub mod prelude {
-    pub use flowy_folder_data_model::entities::{app::*, trash::*, view::*, workspace::*};
-
     pub use crate::{errors::*, event_map::*};
 }
 

+ 1 - 1
frontend/rust-lib/flowy-folder/src/manager.rs

@@ -1,3 +1,4 @@
+use crate::entities::view::ViewDataType;
 use crate::{
     dart_notification::{send_dart_notification, FolderNotification},
     entities::workspace::RepeatedWorkspace,
@@ -10,7 +11,6 @@ use crate::{
 };
 use bytes::Bytes;
 use flowy_error::FlowyError;
-use flowy_folder_data_model::entities::view::ViewDataType;
 use flowy_folder_data_model::user_default;
 use flowy_revision::disk::SQLiteTextBlockRevisionPersistence;
 use flowy_revision::{RevisionManager, RevisionPersistence, RevisionWebSocket};

+ 23 - 26
frontend/rust-lib/flowy-folder/src/services/persistence/version_1/trash_sql.rs

@@ -1,14 +1,11 @@
-use crate::{
-    entities::trash::{Trash, TrashType},
-    errors::FlowyError,
-};
+use crate::errors::FlowyError;
 use diesel::sql_types::Integer;
 use flowy_database::{
     prelude::*,
     schema::{trash_table, trash_table::dsl},
     SqliteConnection,
 };
-use flowy_folder_data_model::revision::TrashRevision;
+use flowy_folder_data_model::revision::{TrashRevision, TrashTypeRevision};
 
 pub struct TrashTableSql();
 impl TrashTableSql {
@@ -64,18 +61,18 @@ pub(crate) struct TrashTable {
     pub create_time: i64,
     pub ty: SqlTrashType,
 }
-impl std::convert::From<TrashTable> for Trash {
-    fn from(table: TrashTable) -> Self {
-        Trash {
-            id: table.id,
-            name: table.name,
-            modified_time: table.modified_time,
-            create_time: table.create_time,
-            ty: table.ty.into(),
-        }
-    }
-}
-
+// impl std::convert::From<TrashTable> for Trash {
+//     fn from(table: TrashTable) -> Self {
+//         Trash {
+//             id: table.id,
+//             name: table.name,
+//             modified_time: table.modified_time,
+//             create_time: table.create_time,
+//             ty: table.ty.into(),
+//         }
+//     }
+// }
+//
 impl std::convert::From<TrashTable> for TrashRevision {
     fn from(trash: TrashTable) -> Self {
         TrashRevision {
@@ -141,22 +138,22 @@ impl std::convert::From<i32> for SqlTrashType {
 
 impl_sql_integer_expression!(SqlTrashType);
 
-impl std::convert::From<SqlTrashType> for TrashType {
+impl std::convert::From<SqlTrashType> for TrashTypeRevision {
     fn from(ty: SqlTrashType) -> Self {
         match ty {
-            SqlTrashType::Unknown => TrashType::Unknown,
-            SqlTrashType::View => TrashType::TrashView,
-            SqlTrashType::App => TrashType::TrashApp,
+            SqlTrashType::Unknown => TrashTypeRevision::Unknown,
+            SqlTrashType::View => TrashTypeRevision::TrashView,
+            SqlTrashType::App => TrashTypeRevision::TrashApp,
         }
     }
 }
 
-impl std::convert::From<TrashType> for SqlTrashType {
-    fn from(ty: TrashType) -> Self {
+impl std::convert::From<TrashTypeRevision> for SqlTrashType {
+    fn from(ty: TrashTypeRevision) -> Self {
         match ty {
-            TrashType::Unknown => SqlTrashType::Unknown,
-            TrashType::TrashView => SqlTrashType::View,
-            TrashType::TrashApp => SqlTrashType::App,
+            TrashTypeRevision::Unknown => SqlTrashType::Unknown,
+            TrashTypeRevision::TrashView => SqlTrashType::View,
+            TrashTypeRevision::TrashApp => SqlTrashType::App,
         }
     }
 }

+ 6 - 6
frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs

@@ -1,7 +1,7 @@
 use crate::{
     entities::{
         trash::{Trash, TrashType},
-        view::{UpdateViewParams, ViewDataType},
+        view::UpdateViewParams,
     },
     errors::FlowyError,
     services::persistence::version_1::app_sql::AppTable,
@@ -13,7 +13,7 @@ use flowy_database::{
     SqliteConnection,
 };
 
-use flowy_folder_data_model::revision::ViewRevision;
+use flowy_folder_data_model::revision::{ViewDataTypeRevision, ViewRevision};
 use lib_infra::util::timestamp;
 
 pub struct ViewTableSql();
@@ -87,8 +87,8 @@ pub(crate) struct ViewTable {
 impl ViewTable {
     pub fn new(view_rev: ViewRevision) -> Self {
         let data_type = match view_rev.data_type {
-            ViewDataType::TextBlock => SqlViewDataType::Block,
-            ViewDataType::Grid => SqlViewDataType::Grid,
+            ViewDataTypeRevision::TextBlock => SqlViewDataType::Block,
+            ViewDataTypeRevision::Grid => SqlViewDataType::Grid,
         };
 
         ViewTable {
@@ -110,8 +110,8 @@ impl ViewTable {
 impl std::convert::From<ViewTable> for ViewRevision {
     fn from(table: ViewTable) -> Self {
         let data_type = match table.view_type {
-            SqlViewDataType::Block => ViewDataType::TextBlock,
-            SqlViewDataType::Grid => ViewDataType::Grid,
+            SqlViewDataType::Block => ViewDataTypeRevision::TextBlock,
+            SqlViewDataType::Grid => ViewDataTypeRevision::Grid,
         };
 
         ViewRevision {

+ 1 - 1
frontend/rust-lib/flowy-folder/src/services/trash/controller.rs

@@ -51,7 +51,7 @@ impl TrashController {
 
         let identifier = TrashId {
             id: trash.id,
-            ty: trash.ty,
+            ty: trash.ty.into(),
         };
 
         let _ = self.delete_trash_on_server(RepeatedTrashId {

+ 17 - 12
frontend/rust-lib/flowy-folder/src/services/view/controller.rs

@@ -1,3 +1,5 @@
+pub use crate::entities::view::ViewDataType;
+use crate::entities::ViewInfo;
 use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
 use crate::{
     dart_notification::{send_dart_notification, FolderNotification},
@@ -14,9 +16,7 @@ use crate::{
 };
 use bytes::Bytes;
 use flowy_database::kv::KV;
-use flowy_folder_data_model::entities::view::{gen_view_id, ViewDataType};
-use flowy_folder_data_model::entities::ViewInfo;
-use flowy_folder_data_model::revision::ViewRevision;
+use flowy_folder_data_model::revision::{gen_view_id, ViewRevision};
 use flowy_sync::entities::text_block::TextBlockId;
 use futures::{FutureExt, StreamExt};
 use std::{collections::HashSet, sync::Arc};
@@ -58,7 +58,7 @@ impl ViewController {
         &self,
         mut params: CreateViewParams,
     ) -> Result<ViewRevision, FlowyError> {
-        let processor = self.get_data_processor(&params.data_type)?;
+        let processor = self.get_data_processor(params.data_type.clone())?;
         let user_id = self.user.user_id()?;
         if params.data.is_empty() {
             let view_data = processor.create_default_view(&user_id, &params.view_id).await?;
@@ -88,7 +88,7 @@ impl ViewController {
             return Err(FlowyError::internal().context("The content of the view should not be empty"));
         }
         let user_id = self.user.user_id()?;
-        let processor = self.get_data_processor(&data_type)?;
+        let processor = self.get_data_processor(data_type)?;
         let _ = processor.create_container(&user_id, view_id, delta_data).await?;
         Ok(())
     }
@@ -140,7 +140,7 @@ impl ViewController {
                     belong_to_id: view_rev.belong_to_id,
                     name: view_rev.name,
                     desc: view_rev.desc,
-                    data_type: view_rev.data_type,
+                    data_type: view_rev.data_type.into(),
                     belongings: RepeatedView { items },
                     ext_data: view_rev.ext_data,
                 };
@@ -209,14 +209,14 @@ impl ViewController {
             .begin_transaction(|transaction| transaction.read_view(view_id))
             .await?;
 
-        let processor = self.get_data_processor(&view_rev.data_type)?;
+        let processor = self.get_data_processor(view_rev.data_type.clone())?;
         let delta_bytes = processor.get_delta_data(view_id).await?;
         let duplicate_params = CreateViewParams {
             belong_to_id: view_rev.belong_to_id.clone(),
             name: format!("{} (copy)", &view_rev.name),
             desc: view_rev.desc,
             thumbnail: view_rev.thumbnail,
-            data_type: view_rev.data_type,
+            data_type: view_rev.data_type.into(),
             data: delta_bytes.to_vec(),
             view_id: gen_view_id(),
             plugin_type: view_rev.plugin_type,
@@ -360,12 +360,16 @@ impl ViewController {
             .persistence
             .begin_transaction(|transaction| transaction.read_view(view_id))
             .await?;
-        self.get_data_processor(&view.data_type)
+        self.get_data_processor(view.data_type)
     }
 
     #[inline]
-    fn get_data_processor(&self, data_type: &ViewDataType) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
-        match self.data_processors.get(data_type) {
+    fn get_data_processor<T: Into<ViewDataType>>(
+        &self,
+        data_type: T,
+    ) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
+        let data_type = data_type.into();
+        match self.data_processors.get(&data_type) {
             None => Err(FlowyError::internal().context(format!(
                 "Get data processor failed. Unknown view data type: {:?}",
                 data_type
@@ -429,7 +433,8 @@ async fn handle_trash_event(
                     .await?;
 
                 for view in views {
-                    match get_data_processor(data_processors.clone(), &view.data_type) {
+                    let data_type = view.data_type.clone().into();
+                    match get_data_processor(data_processors.clone(), &data_type) {
                         Ok(processor) => {
                             let _ = processor.close_container(&view.id).await?;
                         }

+ 2 - 2
frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs

@@ -1,3 +1,5 @@
+use crate::entities::view::{MoveFolderItemParams, MoveFolderItemPayload, MoveFolderItemType};
+use crate::entities::ViewInfo;
 use crate::manager::FolderManager;
 use crate::services::{notify_workspace_setting_did_change, AppController};
 use crate::{
@@ -10,8 +12,6 @@ use crate::{
     errors::FlowyError,
     services::{TrashController, ViewController},
 };
-use flowy_folder_data_model::entities::view::{MoveFolderItemParams, MoveFolderItemPayload, MoveFolderItemType};
-use flowy_folder_data_model::entities::ViewInfo;
 use flowy_folder_data_model::revision::TrashRevision;
 use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
 use std::{convert::TryInto, sync::Arc};

+ 1 - 1
frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs

@@ -1,3 +1,4 @@
+use crate::entities::workspace::*;
 use crate::manager::FolderManager;
 use crate::{
     dart_notification::*,
@@ -9,7 +10,6 @@ use crate::{
     },
 };
 use flowy_database::kv::KV;
-use flowy_folder_data_model::entities::workspace::*;
 use flowy_folder_data_model::revision::{AppRevision, WorkspaceRevision};
 use std::sync::Arc;
 

+ 5 - 5
frontend/rust-lib/flowy-folder/src/services/workspace/event_handler.rs

@@ -1,14 +1,14 @@
+use crate::entities::{
+    app::RepeatedApp,
+    view::View,
+    workspace::{CurrentWorkspaceSetting, RepeatedWorkspace, WorkspaceId, *},
+};
 use crate::{
     dart_notification::{send_dart_notification, FolderNotification},
     errors::FlowyError,
     manager::FolderManager,
     services::{get_current_workspace, read_local_workspace_apps, WorkspaceController},
 };
-use flowy_folder_data_model::entities::{
-    app::RepeatedApp,
-    view::View,
-    workspace::{CurrentWorkspaceSetting, RepeatedWorkspace, WorkspaceId, *},
-};
 use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
 use std::{convert::TryInto, sync::Arc};
 

+ 1 - 1
frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs

@@ -1,6 +1,6 @@
 use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
+use flowy_folder::entities::view::ViewDataType;
 use flowy_folder::entities::workspace::CreateWorkspacePayload;
-use flowy_folder_data_model::entities::view::ViewDataType;
 
 use flowy_revision::disk::RevisionState;
 use flowy_test::{event_builder::*, FlowySDKTest};

+ 8 - 8
frontend/rust-lib/flowy-folder/tests/workspace/script.rs

@@ -1,19 +1,19 @@
-use flowy_folder::event_map::FolderEvent::*;
-use flowy_folder::{errors::ErrorCode, services::folder_editor::FolderEditor};
-use flowy_folder_data_model::entities::view::{RepeatedViewId, ViewId};
-use flowy_folder_data_model::entities::workspace::WorkspaceId;
-use flowy_folder_data_model::entities::{
+use flowy_folder::entities::view::{RepeatedViewId, ViewId};
+use flowy_folder::entities::workspace::WorkspaceId;
+use flowy_folder::entities::{
     app::{App, RepeatedApp},
     trash::Trash,
     view::{RepeatedView, View, ViewDataType},
     workspace::Workspace,
 };
-use flowy_folder_data_model::entities::{
+use flowy_folder::entities::{
     app::{AppId, CreateAppPayload, UpdateAppPayload},
     trash::{RepeatedTrash, TrashId, TrashType},
     view::{CreateViewPayload, UpdateViewPayload},
     workspace::{CreateWorkspacePayload, RepeatedWorkspace},
 };
+use flowy_folder::event_map::FolderEvent::*;
+use flowy_folder::{errors::ErrorCode, services::folder_editor::FolderEditor};
 
 use flowy_revision::disk::RevisionState;
 use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
@@ -205,7 +205,7 @@ impl FolderTest {
                 restore_view_from_trash(sdk, &self.view.id).await;
             }
             FolderScript::ReadTrash => {
-                let trash = read_trash(sdk).await;
+                let mut trash = read_trash(sdk).await;
                 self.trash = trash.into_inner();
             }
             FolderScript::DeleteAllTrash => {
@@ -264,7 +264,7 @@ pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Wor
 
 pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) -> Vec<Workspace> {
     let request = WorkspaceId { value: workspace_id };
-    let repeated_workspace = FolderEventBuilder::new(sdk.clone())
+    let mut repeated_workspace = FolderEventBuilder::new(sdk.clone())
         .event(ReadWorkspaces)
         .payload(request.clone())
         .async_send()

+ 1 - 1
frontend/rust-lib/flowy-net/src/http_server/folder.rs

@@ -3,7 +3,7 @@ use crate::{
     request::{HttpRequestBuilder, ResponseMiddleware},
 };
 use flowy_error::FlowyError;
-use flowy_folder_data_model::entities::{
+use flowy_folder::entities::{
     trash::RepeatedTrashId,
     view::{CreateViewParams, RepeatedViewId, UpdateViewParams, ViewId},
     workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceId},

+ 5 - 5
frontend/rust-lib/flowy-net/src/local_server/server.rs

@@ -252,15 +252,15 @@ impl RevisionUser for LocalRevisionUser {
     }
 }
 
-use flowy_folder_data_model::entities::app::gen_app_id;
-use flowy_folder_data_model::entities::workspace::gen_workspace_id;
-use flowy_folder_data_model::entities::{
+use flowy_folder::entities::{
     app::{AppId, CreateAppParams, UpdateAppParams},
     trash::RepeatedTrashId,
     view::{CreateViewParams, RepeatedViewId, UpdateViewParams, ViewId},
     workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceId},
 };
-use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
+use flowy_folder_data_model::revision::{
+    gen_app_id, gen_workspace_id, AppRevision, TrashRevision, ViewRevision, WorkspaceRevision,
+};
 use flowy_text_block::BlockCloudService;
 use flowy_user::event_map::UserCloudService;
 use flowy_user_data_model::entities::{
@@ -308,7 +308,7 @@ impl FolderCouldServiceV1 for LocalServer {
             belong_to_id: params.belong_to_id,
             name: params.name,
             desc: params.desc,
-            data_type: params.data_type,
+            data_type: params.data_type.into(),
             version: 0,
             belongings: vec![],
             modified_time: time,

+ 1 - 1
frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs

@@ -1,7 +1,7 @@
 use bytes::Bytes;
 use flowy_database::ConnectionPool;
+use flowy_folder::entities::ViewDataType;
 use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap};
-use flowy_folder::prelude::ViewDataType;
 use flowy_folder::{
     errors::{internal_error, FlowyError},
     event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser},

+ 1 - 1
frontend/rust-lib/flowy-test/src/helper.rs

@@ -1,5 +1,5 @@
 use crate::prelude::*;
-use flowy_folder::prelude::WorkspaceId;
+use flowy_folder::entities::WorkspaceId;
 use flowy_folder::{
     entities::{
         app::*,

+ 1 - 1
frontend/rust-lib/flowy-user/src/handlers/user_handler.rs

@@ -20,7 +20,7 @@ pub async fn check_user_handler(session: AppData<Arc<UserSession>>) -> DataResul
 
 #[tracing::instrument(level = "debug", skip(session))]
 pub async fn get_user_profile_handler(session: AppData<Arc<UserSession>>) -> DataResult<UserProfile, FlowyError> {
-    let user_profile = session.user_profile().await?;
+    let user_profile = session.get_user_profile().await?;
     data_result(user_profile)
 }
 

+ 24 - 20
frontend/rust-lib/flowy-user/src/services/user_session.rs

@@ -82,7 +82,7 @@ impl UserSession {
     #[tracing::instrument(level = "debug", skip(self))]
     pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, FlowyError> {
         if self.is_user_login(&params.email) {
-            self.user_profile().await
+            self.get_user_profile().await
         } else {
             let resp = self.cloud_service.sign_in(params).await?;
             let session: Session = resp.clone().into();
@@ -97,7 +97,7 @@ impl UserSession {
     #[tracing::instrument(level = "debug", skip(self))]
     pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, FlowyError> {
         if self.is_user_login(&params.email) {
-            self.user_profile().await
+            self.get_user_profile().await
         } else {
             let resp = self.cloud_service.sign_up(params).await?;
             let session: Session = resp.clone().into();
@@ -131,6 +131,10 @@ impl UserSession {
         let changeset = UserTableChangeset::new(params.clone());
         diesel_update_table!(user_table, changeset, &*self.db_connection()?);
 
+        let user_profile = self.get_user_profile().await?;
+        dart_notify(&session.token, UserNotification::UserProfileUpdated)
+            .payload(user_profile)
+            .send();
         let _ = self.update_user_on_server(&session.token, params).await?;
         Ok(())
     }
@@ -150,7 +154,7 @@ impl UserSession {
         Ok(user.into())
     }
 
-    pub async fn user_profile(&self) -> Result<UserProfile, FlowyError> {
+    pub async fn get_user_profile(&self) -> Result<UserProfile, FlowyError> {
         let (user_id, token) = self.get_session()?.into_part();
         let user = dsl::user_table
             .filter(user_table::id.eq(&user_id))
@@ -179,23 +183,23 @@ impl UserSession {
 }
 
 impl UserSession {
-    fn read_user_profile_on_server(&self, token: &str) -> Result<(), FlowyError> {
-        let server = self.cloud_service.clone();
-        let token = token.to_owned();
-        tokio::spawn(async move {
-            match server.get_user(&token).await {
-                Ok(profile) => {
-                    dart_notify(&token, UserNotification::UserProfileUpdated)
-                        .payload(profile)
-                        .send();
-                }
-                Err(e) => {
-                    dart_notify(&token, UserNotification::UserProfileUpdated)
-                        .error(e)
-                        .send();
-                }
-            }
-        });
+    fn read_user_profile_on_server(&self, _token: &str) -> Result<(), FlowyError> {
+        // let server = self.cloud_service.clone();
+        // let token = token.to_owned();
+        // tokio::spawn(async move {
+        //     match server.get_user(&token).await {
+        //         Ok(profile) => {
+        //             dart_notify(&token, UserNotification::UserProfileUpdated)
+        //                 .payload(profile)
+        //                 .send();
+        //         }
+        //         Err(e) => {
+        //             dart_notify(&token, UserNotification::UserProfileUpdated)
+        //                 .error(e)
+        //                 .send();
+        //         }
+        //     }
+        // });
         Ok(())
     }
 

+ 0 - 2
shared-lib/flowy-folder-data-model/Flowy.toml

@@ -1,2 +0,0 @@
-# Check out the FlowyConfig (located in flowy_toml.rs) for more details.
-proto_input = ["src/entities",]

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