Browse Source

Merge pull request #585 from AppFlowy-IO/feat/update_user_profile

chore: update user name with UserService
Nathan.fooo 2 years ago
parent
commit
1f47221fc9
30 changed files with 411 additions and 307 deletions
  1. 39 0
      frontend/app_flowy/lib/core/folder_notification.dart
  2. 39 0
      frontend/app_flowy/lib/core/grid_notification.dart
  3. 0 62
      frontend/app_flowy/lib/core/notification_helper.dart
  4. 39 0
      frontend/app_flowy/lib/core/user_notification.dart
  5. 6 10
      frontend/app_flowy/lib/startup/deps_resolver.dart
  6. 90 57
      frontend/app_flowy/lib/user/application/user_listener.dart
  7. 29 2
      frontend/app_flowy/lib/user/application/user_service.dart
  8. 0 3
      frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart
  9. 1 1
      frontend/app_flowy/lib/workspace/application/app/app_listener.dart
  10. 1 2
      frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart
  11. 1 1
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_listener.dart
  12. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart
  13. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart
  14. 1 1
      frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart
  15. 4 6
      frontend/app_flowy/lib/workspace/application/home/home_bloc.dart
  16. 1 1
      frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart
  17. 42 27
      frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart
  18. 1 1
      frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart
  19. 1 1
      frontend/app_flowy/lib/workspace/application/view/view_listener.dart
  20. 5 5
      frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart
  21. 36 60
      frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart
  22. 2 2
      frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart
  23. 7 3
      frontend/rust-lib/flowy-net/src/http_server/user.rs
  24. 2 2
      frontend/rust-lib/flowy-net/src/local_server/server.rs
  25. 5 5
      frontend/rust-lib/flowy-user/src/event_map.rs
  26. 7 7
      frontend/rust-lib/flowy-user/src/handlers/user_handler.rs
  27. 2 2
      frontend/rust-lib/flowy-user/src/services/database.rs
  28. 28 24
      frontend/rust-lib/flowy-user/src/services/user_session.rs
  29. 13 13
      frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs
  30. 7 7
      shared-lib/flowy-user-data-model/src/entities/user_profile.rs

+ 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();
+  }
+}

+ 6 - 10
frontend/app_flowy/lib/startup/deps_resolver.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),
   );
 
   //
@@ -60,8 +60,8 @@ void _resolveHomeDeps(GetIt getIt) {
 
   getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
     (user, _) => WelcomeBloc(
-      userService: UserService(),
-      userListener: getIt<UserListener>(param1: user),
+      userService: UserService(userId: user.id),
+      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,11 +98,7 @@ void _resolveFolderDeps(GetIt getIt) {
   );
 
   getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
-    (user, _) => MenuUserBloc(
-      user,
-      UserService(),
-      getIt<UserListener>(param1: user),
-    ),
+    (user, _) => MenuUserBloc(user),
   );
 
   // App

+ 90 - 57
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-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;
   }
 }

+ 29 - 2
frontend/app_flowy/lib/user/application/user_service.dart

@@ -1,15 +1,42 @@
 import 'dart:async';
+
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.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-user-data-model/user_profile.pb.dart';
 
 class UserService {
-  Future<Either<UserProfile, FlowyError>> fetchUserProfile({required String userId}) {
+  final String userId;
+  UserService({
+    required this.userId,
+  });
+  Future<Either<UserProfile, FlowyError>> getUserProfile({required String userId}) {
     return UserEventGetUserProfile().send();
   }
 
+  Future<Either<Unit, FlowyError>> updateUserProfile({
+    String? name,
+    String? password,
+    String? email,
+  }) {
+    var payload = UpdateUserProfilePayload.create()..id = userId;
+
+    if (name != null) {
+      payload.name = name;
+    }
+
+    if (password != null) {
+      payload.password = password;
+    }
+
+    if (email != null) {
+      payload.email = email;
+    }
+
+    return UserEventUpdateUserProfile(payload).send();
+  }
+
   Future<Either<Unit, FlowyError>> deleteWorkspace({required String workspaceId}) {
     throw UnimplementedError();
   }

+ 0 - 3
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';
@@ -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/workspace/application/app/app_listener.dart

@@ -1,7 +1,7 @@
 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';

+ 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/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';
 

+ 4 - 6
frontend/app_flowy/lib/workspace/application/home/home_bloc.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),

+ 1 - 1
frontend/app_flowy/lib/workspace/application/menu/menu_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 {

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

@@ -11,49 +11,62 @@ import 'package:dartz/dartz.dart';
 part 'menu_user_bloc.freezed.dart';
 
 class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
-  final UserService userService;
-  final UserListener userListener;
+  final UserService _userService;
+  final UserListener _userListener;
+  final UserWorkspaceListener _userWorkspaceListener;
   final UserProfile userProfile;
 
-  MenuUserBloc(this.userProfile, this.userService, this.userListener) : super(MenuUserState.initial(userProfile)) {
+  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();
   }
 
   Future<void> _initUser() async {
-    final result = await userService.initUser();
+    final result = await _userService.initUser();
     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
   }
 }
 
@@ -61,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/trash/trash_listener.dart

@@ -1,7 +1,7 @@
 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';

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

@@ -1,6 +1,6 @@
 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';

+ 5 - 5
frontend/app_flowy/lib/workspace/application/workspace/welcome_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();
   }
 

+ 36 - 60
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-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;
   }
 }

+ 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);
   }

+ 7 - 3
frontend/rust-lib/flowy-net/src/http_server/user.rs

@@ -2,7 +2,7 @@ use crate::{configuration::*, request::HttpRequestBuilder};
 use flowy_error::FlowyError;
 use flowy_user::event_map::UserCloudService;
 use flowy_user_data_model::entities::{
-    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile,
+    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
 };
 use http_flowy::errors::ServerError;
 use lib_infra::future::FutureResult;
@@ -42,7 +42,7 @@ impl UserCloudService for UserHttpCloudService {
         })
     }
 
-    fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), FlowyError> {
+    fn update_user(&self, token: &str, params: UpdateUserProfileParams) -> FutureResult<(), FlowyError> {
         let token = token.to_owned();
         let url = self.config.user_profile_url();
         FutureResult::new(async move {
@@ -101,7 +101,11 @@ pub async fn get_user_profile_request(token: &str, url: &str) -> Result<UserProf
     Ok(user_profile)
 }
 
-pub async fn update_user_profile_request(token: &str, params: UpdateUserParams, url: &str) -> Result<(), ServerError> {
+pub async fn update_user_profile_request(
+    token: &str,
+    params: UpdateUserProfileParams,
+    url: &str,
+) -> Result<(), ServerError> {
     let _ = request_builder()
         .patch(&url.to_owned())
         .header(HEADER_TOKEN, token)

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

@@ -264,7 +264,7 @@ use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision
 use flowy_text_block::BlockCloudService;
 use flowy_user::event_map::UserCloudService;
 use flowy_user_data_model::entities::{
-    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile,
+    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
 };
 use lib_infra::{future::FutureResult, util::timestamp};
 
@@ -401,7 +401,7 @@ impl UserCloudService for LocalServer {
         FutureResult::new(async { Ok(()) })
     }
 
-    fn update_user(&self, _token: &str, _params: UpdateUserParams) -> FutureResult<(), FlowyError> {
+    fn update_user(&self, _token: &str, _params: UpdateUserProfileParams) -> FutureResult<(), FlowyError> {
         FutureResult::new(async { Ok(()) })
     }
 

+ 5 - 5
frontend/rust-lib/flowy-user/src/event_map.rs

@@ -1,6 +1,6 @@
 use crate::{errors::FlowyError, handlers::*, services::UserSession};
 use flowy_user_data_model::entities::{
-    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile,
+    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
 };
 use lib_dispatch::prelude::*;
 use lib_infra::future::FutureResult;
@@ -15,7 +15,7 @@ pub fn create(user_session: Arc<UserSession>) -> Module {
         .event(UserEvent::InitUser, init_user_handler)
         .event(UserEvent::GetUserProfile, get_user_profile_handler)
         .event(UserEvent::SignOut, sign_out)
-        .event(UserEvent::UpdateUser, update_user_handler)
+        .event(UserEvent::UpdateUserProfile, update_user_profile_handler)
         .event(UserEvent::CheckUser, check_user_handler)
         .event(UserEvent::SetAppearanceSetting, set_appearance_setting)
         .event(UserEvent::GetAppearanceSetting, get_appearance_setting)
@@ -25,7 +25,7 @@ pub trait UserCloudService: Send + Sync {
     fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, FlowyError>;
     fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, FlowyError>;
     fn sign_out(&self, token: &str) -> FutureResult<(), FlowyError>;
-    fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), FlowyError>;
+    fn update_user(&self, token: &str, params: UpdateUserProfileParams) -> FutureResult<(), FlowyError>;
     fn get_user(&self, token: &str) -> FutureResult<UserProfile, FlowyError>;
     fn ws_addr(&self) -> String;
 }
@@ -48,8 +48,8 @@ pub enum UserEvent {
     #[event(passthrough)]
     SignOut = 3,
 
-    #[event(input = "UpdateUserPayload")]
-    UpdateUser = 4,
+    #[event(input = "UpdateUserProfilePayload")]
+    UpdateUserProfile = 4,
 
     #[event(output = "UserProfile")]
     GetUserProfile = 5,

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

@@ -1,7 +1,7 @@
 use crate::{errors::FlowyError, services::UserSession};
 use flowy_database::kv::KV;
 use flowy_user_data_model::entities::{
-    AppearanceSettings, UpdateUserParams, UpdateUserPayload, UserProfile, APPEARANCE_DEFAULT_THEME,
+    AppearanceSettings, UpdateUserProfileParams, UpdateUserProfilePayload, UserProfile, APPEARANCE_DEFAULT_THEME,
 };
 use lib_dispatch::prelude::*;
 use std::{convert::TryInto, sync::Arc};
@@ -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)
 }
 
@@ -30,13 +30,13 @@ pub async fn sign_out(session: AppData<Arc<UserSession>>) -> Result<(), FlowyErr
     Ok(())
 }
 
-#[tracing::instrument(level = "debug", name = "update_user", skip(data, session))]
-pub async fn update_user_handler(
-    data: Data<UpdateUserPayload>,
+#[tracing::instrument(level = "debug", skip(data, session))]
+pub async fn update_user_profile_handler(
+    data: Data<UpdateUserProfilePayload>,
     session: AppData<Arc<UserSession>>,
 ) -> Result<(), FlowyError> {
-    let params: UpdateUserParams = data.into_inner().try_into()?;
-    session.update_user(params).await?;
+    let params: UpdateUserProfileParams = data.into_inner().try_into()?;
+    session.update_user_profile(params).await?;
     Ok(())
 }
 

+ 2 - 2
frontend/rust-lib/flowy-user/src/services/database.rs

@@ -1,7 +1,7 @@
 use flowy_database::ConnectionPool;
 use flowy_database::{schema::user_table, DBConnection, Database};
 use flowy_error::{ErrorCode, FlowyError};
-use flowy_user_data_model::entities::{SignInResponse, SignUpResponse, UpdateUserParams, UserProfile};
+use flowy_user_data_model::entities::{SignInResponse, SignUpResponse, UpdateUserProfileParams, UserProfile};
 use lazy_static::lazy_static;
 use parking_lot::RwLock;
 use std::{collections::HashMap, sync::Arc, time::Duration};
@@ -134,7 +134,7 @@ pub struct UserTableChangeset {
 }
 
 impl UserTableChangeset {
-    pub fn new(params: UpdateUserParams) -> Self {
+    pub fn new(params: UpdateUserProfileParams) -> Self {
         UserTableChangeset {
             id: params.id,
             workspace: None,

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

@@ -15,7 +15,7 @@ use flowy_database::{
     DBConnection, ExpressionMethods, UserDatabaseConnection,
 };
 use flowy_user_data_model::entities::{
-    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile,
+    SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
 };
 use parking_lot::RwLock;
 use serde::{Deserialize, Serialize};
@@ -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();
@@ -126,11 +126,15 @@ impl UserSession {
     }
 
     #[tracing::instrument(level = "debug", skip(self))]
-    pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), FlowyError> {
+    pub async fn update_user_profile(&self, params: UpdateUserProfileParams) -> Result<(), FlowyError> {
         let session = self.get_session()?;
         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,27 +183,27 @@ 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(())
     }
 
-    async fn update_user_on_server(&self, token: &str, params: UpdateUserParams) -> Result<(), FlowyError> {
+    async fn update_user_on_server(&self, token: &str, params: UpdateUserProfileParams) -> Result<(), FlowyError> {
         let server = self.cloud_service.clone();
         let token = token.to_owned();
         let _ = tokio::spawn(async move {
@@ -275,7 +279,7 @@ impl UserSession {
 pub async fn update_user(
     _cloud_service: Arc<dyn UserCloudService>,
     pool: Arc<ConnectionPool>,
-    params: UpdateUserParams,
+    params: UpdateUserProfileParams,
 ) -> Result<(), FlowyError> {
     let changeset = UserTableChangeset::new(params);
     let conn = pool.get()?;

+ 13 - 13
frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs

@@ -1,7 +1,7 @@
 use crate::helper::*;
 use flowy_test::{event_builder::UserModuleEventBuilder, FlowySDKTest};
 use flowy_user::{errors::ErrorCode, event_map::UserEvent::*};
-use flowy_user_data_model::entities::{UpdateUserPayload, UserProfile};
+use flowy_user_data_model::entities::{UpdateUserProfilePayload, UserProfile};
 use nanoid::nanoid;
 
 // use serial_test::*;
@@ -33,9 +33,9 @@ async fn user_update_with_name() {
     let sdk = FlowySDKTest::default();
     let user = sdk.init_user().await;
     let new_name = "hello_world".to_owned();
-    let request = UpdateUserPayload::new(&user.id).name(&new_name);
+    let request = UpdateUserProfilePayload::new(&user.id).name(&new_name);
     let _ = UserModuleEventBuilder::new(sdk.clone())
-        .event(UpdateUser)
+        .event(UpdateUserProfile)
         .payload(request)
         .sync_send();
 
@@ -53,9 +53,9 @@ async fn user_update_with_email() {
     let sdk = FlowySDKTest::default();
     let user = sdk.init_user().await;
     let new_email = format!("{}@gmail.com", nanoid!(6));
-    let request = UpdateUserPayload::new(&user.id).email(&new_email);
+    let request = UpdateUserProfilePayload::new(&user.id).email(&new_email);
     let _ = UserModuleEventBuilder::new(sdk.clone())
-        .event(UpdateUser)
+        .event(UpdateUserProfile)
         .payload(request)
         .sync_send();
     let user_profile = UserModuleEventBuilder::new(sdk.clone())
@@ -72,10 +72,10 @@ async fn user_update_with_password() {
     let sdk = FlowySDKTest::default();
     let user = sdk.init_user().await;
     let new_password = "H123world!".to_owned();
-    let request = UpdateUserPayload::new(&user.id).password(&new_password);
+    let request = UpdateUserProfilePayload::new(&user.id).password(&new_password);
 
     let _ = UserModuleEventBuilder::new(sdk.clone())
-        .event(UpdateUser)
+        .event(UpdateUserProfile)
         .payload(request)
         .sync_send()
         .assert_success();
@@ -86,10 +86,10 @@ async fn user_update_with_invalid_email() {
     let test = FlowySDKTest::default();
     let user = test.init_user().await;
     for email in invalid_email_test_case() {
-        let request = UpdateUserPayload::new(&user.id).email(&email);
+        let request = UpdateUserProfilePayload::new(&user.id).email(&email);
         assert_eq!(
             UserModuleEventBuilder::new(test.clone())
-                .event(UpdateUser)
+                .event(UpdateUserProfile)
                 .payload(request)
                 .sync_send()
                 .error()
@@ -104,10 +104,10 @@ async fn user_update_with_invalid_password() {
     let test = FlowySDKTest::default();
     let user = test.init_user().await;
     for password in invalid_password_test_case() {
-        let request = UpdateUserPayload::new(&user.id).password(&password);
+        let request = UpdateUserProfilePayload::new(&user.id).password(&password);
 
         UserModuleEventBuilder::new(test.clone())
-            .event(UpdateUser)
+            .event(UpdateUserProfile)
             .payload(request)
             .sync_send()
             .assert_error();
@@ -118,9 +118,9 @@ async fn user_update_with_invalid_password() {
 async fn user_update_with_invalid_name() {
     let test = FlowySDKTest::default();
     let user = test.init_user().await;
-    let request = UpdateUserPayload::new(&user.id).name("");
+    let request = UpdateUserProfilePayload::new(&user.id).name("");
     UserModuleEventBuilder::new(test.clone())
-        .event(UpdateUser)
+        .event(UpdateUserProfile)
         .payload(request)
         .sync_send()
         .assert_error();

+ 7 - 7
shared-lib/flowy-user-data-model/src/entities/user_profile.rs

@@ -28,7 +28,7 @@ pub struct UserProfile {
 }
 
 #[derive(ProtoBuf, Default)]
-pub struct UpdateUserPayload {
+pub struct UpdateUserProfilePayload {
     #[pb(index = 1)]
     pub id: String,
 
@@ -42,7 +42,7 @@ pub struct UpdateUserPayload {
     pub password: Option<String>,
 }
 
-impl UpdateUserPayload {
+impl UpdateUserProfilePayload {
     pub fn new(id: &str) -> Self {
         Self {
             id: id.to_owned(),
@@ -67,7 +67,7 @@ impl UpdateUserPayload {
 }
 
 #[derive(ProtoBuf, Default, Clone, Debug)]
-pub struct UpdateUserParams {
+pub struct UpdateUserProfileParams {
     #[pb(index = 1)]
     pub id: String,
 
@@ -81,7 +81,7 @@ pub struct UpdateUserParams {
     pub password: Option<String>,
 }
 
-impl UpdateUserParams {
+impl UpdateUserProfileParams {
     pub fn new(user_id: &str) -> Self {
         Self {
             id: user_id.to_owned(),
@@ -105,10 +105,10 @@ impl UpdateUserParams {
     }
 }
 
-impl TryInto<UpdateUserParams> for UpdateUserPayload {
+impl TryInto<UpdateUserProfileParams> for UpdateUserProfilePayload {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<UpdateUserParams, Self::Error> {
+    fn try_into(self) -> Result<UpdateUserProfileParams, Self::Error> {
         let id = UserId::parse(self.id)?.0;
 
         let name = match self.name {
@@ -126,7 +126,7 @@ impl TryInto<UpdateUserParams> for UpdateUserPayload {
             Some(password) => Some(UserPassword::parse(password)?.0),
         };
 
-        Ok(UpdateUserParams {
+        Ok(UpdateUserProfileParams {
             id,
             name,
             email,