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

chore: update user name with UserService
This commit is contained in:
Nathan.fooo 2022-07-04 11:20:32 +08:00 committed by GitHub
commit 1f47221fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 422 additions and 318 deletions

View File

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

View File

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

View File

@ -1,68 +1,6 @@
import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart'; 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: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> { class NotificationParser<T, E> {
String? id; String? id;

View File

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

View File

@ -52,7 +52,7 @@ void _resolveHomeDeps(GetIt getIt) {
getIt.registerSingleton(MenuSharedState()); getIt.registerSingleton(MenuSharedState());
getIt.registerFactoryParam<UserListener, UserProfile, void>( 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>( getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
(user, _) => WelcomeBloc( (user, _) => WelcomeBloc(
userService: UserService(), 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) { void _resolveFolderDeps(GetIt getIt) {
//workspace //workspace
getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>((user, workspaceId) => getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>(
WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId))); (user, workspaceId) => WorkspaceListener(user: user, workspaceId: workspaceId));
// View // View
getIt.registerFactoryParam<ViewListener, View, void>( getIt.registerFactoryParam<ViewListener, View, void>(
@ -98,11 +98,7 @@ void _resolveFolderDeps(GetIt getIt) {
); );
getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>( getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
(user, _) => MenuUserBloc( (user, _) => MenuUserBloc(user),
user,
UserService(),
getIt<UserListener>(param1: user),
),
); );
// App // App

View File

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

View File

@ -1,15 +1,42 @@
import 'dart:async'; import 'dart:async';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.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-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'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
class UserService { 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(); 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}) { Future<Either<Unit, FlowyError>> deleteWorkspace({required String workspaceId}) {
throw UnimplementedError(); throw UnimplementedError();
} }

View File

@ -1,5 +1,4 @@
import 'package:app_flowy/user/application/auth_service.dart'; 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/router.dart';
import 'package:app_flowy/user/presentation/widgets/background.dart'; import 'package:app_flowy/user/presentation/widgets/background.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@ -34,8 +33,6 @@ class SkipLogInScreen extends StatefulWidget {
} }
class _SkipLogInScreenState extends State<SkipLogInScreen> { class _SkipLogInScreenState extends State<SkipLogInScreen> {
UserListener? userListener;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(

View File

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:app_flowy/core/folder_notification.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:app_flowy/core/notification_helper.dart';
import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.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-error/errors.pb.dart';

View File

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

View File

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

View File

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

View File

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

View File

@ -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-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.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_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_infra/notifier.dart'; import 'package:flowy_infra/notifier.dart';
import 'dart:async'; import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:app_flowy/core/notification_helper.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';

View File

@ -11,19 +11,17 @@ import 'package:dartz/dartz.dart';
part 'home_bloc.freezed.dart'; part 'home_bloc.freezed.dart';
class HomeBloc extends Bloc<HomeEvent, HomeState> { class HomeBloc extends Bloc<HomeEvent, HomeState> {
final UserListener _listener; final UserWorkspaceListener _listener;
HomeBloc(UserProfile user, CurrentWorkspaceSetting workspaceSetting) HomeBloc(UserProfile user, CurrentWorkspaceSetting workspaceSetting)
: _listener = UserListener(user: user), : _listener = UserWorkspaceListener(userProfile: user),
super(HomeState.initial(workspaceSetting)) { super(HomeState.initial(workspaceSetting)) {
on<HomeEvent>((event, emit) async { on<HomeEvent>((event, emit) async {
await event.map( await event.map(
initial: (_Initial value) { initial: (_Initial value) {
_listener.start( _listener.start(
onAuthChanged: (result) { onAuthChanged: (result) => _authDidChanged(result),
_authDidChanged(result); onSettingUpdated: (result) {
},
onWorkspaceSettingUpdated: (result) {
result.fold( result.fold(
(setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)), (setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)),
(r) => Log.error(r), (r) => Log.error(r),

View File

@ -22,7 +22,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
on<MenuEvent>((event, emit) async { on<MenuEvent>((event, emit) async {
await event.map( await event.map(
initial: (e) async { initial: (e) async {
listener.start(addAppCallback: _handleAppsOrFail); listener.start(appsChanged: _handleAppsOrFail);
await _fetchApps(emit); await _fetchApps(emit);
}, },
openPage: (e) async { openPage: (e) async {

View File

@ -11,49 +11,62 @@ import 'package:dartz/dartz.dart';
part 'menu_user_bloc.freezed.dart'; part 'menu_user_bloc.freezed.dart';
class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> { class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
final UserService userService; final UserService _userService;
final UserListener userListener; final UserListener _userListener;
final UserWorkspaceListener _userWorkspaceListener;
final UserProfile userProfile; 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 { on<MenuUserEvent>((event, emit) async {
await event.map( await event.when(
initial: (_) async { initial: () async {
userListener.start( _userListener.start(onProfileUpdated: _profileUpdated);
onProfileUpdated: _profileUpdated, _userWorkspaceListener.start(onWorkspacesUpdated: _workspaceListUpdated);
onWorkspaceListUpdated: _workspaceListUpdated,
);
await _initUser(); 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 @override
Future<void> close() async { Future<void> close() async {
await userListener.stop(); await _userListener.stop();
await _userWorkspaceListener.stop();
super.close(); super.close();
} }
Future<void> _initUser() async { Future<void> _initUser() async {
final result = await userService.initUser(); final result = await _userService.initUser();
result.fold((l) => null, (error) => Log.error(error)); 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) { void _workspaceListUpdated(Either<List<Workspace>, FlowyError> workspacesOrFailed) {
// fetch workspaces // Do nothing by now
// iUserImpl.fetchWorkspaces().then((result) {
// result.fold(
// (workspaces) async* {
// yield state.copyWith(workspaces: some(workspaces));
// },
// (error) async* {
// yield state.copyWith(successOrFailure: right(error.msg));
// },
// );
// });
} }
} }
@ -61,18 +74,20 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
class MenuUserEvent with _$MenuUserEvent { class MenuUserEvent with _$MenuUserEvent {
const factory MenuUserEvent.initial() = _Initial; const factory MenuUserEvent.initial() = _Initial;
const factory MenuUserEvent.fetchWorkspaces() = _FetchWorkspaces; const factory MenuUserEvent.fetchWorkspaces() = _FetchWorkspaces;
const factory MenuUserEvent.updateUserName(String name) = _UpdateUserName;
const factory MenuUserEvent.didReceiveUserProfile(UserProfile newUserProfile) = _DidReceiveUserProfile;
} }
@freezed @freezed
class MenuUserState with _$MenuUserState { class MenuUserState with _$MenuUserState {
const factory MenuUserState({ const factory MenuUserState({
required UserProfile user, required UserProfile userProfile,
required Option<List<Workspace>> workspaces, required Option<List<Workspace>> workspaces,
required Either<Unit, String> successOrFailure, required Either<Unit, String> successOrFailure,
}) = _MenuUserState; }) = _MenuUserState;
factory MenuUserState.initial(UserProfile user) => MenuUserState( factory MenuUserState.initial(UserProfile userProfile) => MenuUserState(
user: user, userProfile: userProfile,
workspaces: none(), workspaces: none(),
successOrFailure: left(unit), successOrFailure: left(unit),
); );

View File

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:app_flowy/core/folder_notification.dart';
import 'package:dartz/dartz.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/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.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-error/errors.pb.dart';

View File

@ -1,6 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:typed_data'; 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:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.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-data-model/view.pb.dart';

View File

@ -11,13 +11,13 @@ part 'welcome_bloc.freezed.dart';
class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> { class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
final UserService userService; final UserService userService;
final UserListener userListener; final UserWorkspaceListener userWorkspaceListener;
WelcomeBloc({required this.userService, required this.userListener}) : super(WelcomeState.initial()) { WelcomeBloc({required this.userService, required this.userWorkspaceListener}) : super(WelcomeState.initial()) {
on<WelcomeEvent>( on<WelcomeEvent>(
(event, emit) async { (event, emit) async {
await event.map(initial: (e) async { await event.map(initial: (e) async {
userListener.start( userWorkspaceListener.start(
onWorkspaceListUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)), onWorkspacesUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)),
); );
// //
await _fetchWorkspaces(emit); await _fetchWorkspaces(emit);
@ -37,7 +37,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
@override @override
Future<void> close() async { Future<void> close() async {
await userListener.stop(); await userWorkspaceListener.stop();
super.close(); super.close();
} }

View File

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

View File

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

View File

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

View File

@ -264,7 +264,7 @@ use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision
use flowy_text_block::BlockCloudService; use flowy_text_block::BlockCloudService;
use flowy_user::event_map::UserCloudService; use flowy_user::event_map::UserCloudService;
use flowy_user_data_model::entities::{ 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}; use lib_infra::{future::FutureResult, util::timestamp};
@ -401,7 +401,7 @@ impl UserCloudService for LocalServer {
FutureResult::new(async { Ok(()) }) 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(()) }) FutureResult::new(async { Ok(()) })
} }

View File

@ -1,6 +1,6 @@
use crate::{errors::FlowyError, handlers::*, services::UserSession}; use crate::{errors::FlowyError, handlers::*, services::UserSession};
use flowy_user_data_model::entities::{ use flowy_user_data_model::entities::{
SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile, SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
}; };
use lib_dispatch::prelude::*; use lib_dispatch::prelude::*;
use lib_infra::future::FutureResult; 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::InitUser, init_user_handler)
.event(UserEvent::GetUserProfile, get_user_profile_handler) .event(UserEvent::GetUserProfile, get_user_profile_handler)
.event(UserEvent::SignOut, sign_out) .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::CheckUser, check_user_handler)
.event(UserEvent::SetAppearanceSetting, set_appearance_setting) .event(UserEvent::SetAppearanceSetting, set_appearance_setting)
.event(UserEvent::GetAppearanceSetting, get_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_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, FlowyError>;
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, FlowyError>; fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, FlowyError>;
fn sign_out(&self, token: &str) -> FutureResult<(), 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 get_user(&self, token: &str) -> FutureResult<UserProfile, FlowyError>;
fn ws_addr(&self) -> String; fn ws_addr(&self) -> String;
} }
@ -48,8 +48,8 @@ pub enum UserEvent {
#[event(passthrough)] #[event(passthrough)]
SignOut = 3, SignOut = 3,
#[event(input = "UpdateUserPayload")] #[event(input = "UpdateUserProfilePayload")]
UpdateUser = 4, UpdateUserProfile = 4,
#[event(output = "UserProfile")] #[event(output = "UserProfile")]
GetUserProfile = 5, GetUserProfile = 5,

View File

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

View File

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

View File

@ -15,7 +15,7 @@ use flowy_database::{
DBConnection, ExpressionMethods, UserDatabaseConnection, DBConnection, ExpressionMethods, UserDatabaseConnection,
}; };
use flowy_user_data_model::entities::{ use flowy_user_data_model::entities::{
SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile, SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile,
}; };
use parking_lot::RwLock; use parking_lot::RwLock;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -82,7 +82,7 @@ impl UserSession {
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, FlowyError> { pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, FlowyError> {
if self.is_user_login(&params.email) { if self.is_user_login(&params.email) {
self.user_profile().await self.get_user_profile().await
} else { } else {
let resp = self.cloud_service.sign_in(params).await?; let resp = self.cloud_service.sign_in(params).await?;
let session: Session = resp.clone().into(); let session: Session = resp.clone().into();
@ -97,7 +97,7 @@ impl UserSession {
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, FlowyError> { pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, FlowyError> {
if self.is_user_login(&params.email) { if self.is_user_login(&params.email) {
self.user_profile().await self.get_user_profile().await
} else { } else {
let resp = self.cloud_service.sign_up(params).await?; let resp = self.cloud_service.sign_up(params).await?;
let session: Session = resp.clone().into(); let session: Session = resp.clone().into();
@ -126,11 +126,15 @@ impl UserSession {
} }
#[tracing::instrument(level = "debug", skip(self))] #[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 session = self.get_session()?;
let changeset = UserTableChangeset::new(params.clone()); let changeset = UserTableChangeset::new(params.clone());
diesel_update_table!(user_table, changeset, &*self.db_connection()?); 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?; let _ = self.update_user_on_server(&session.token, params).await?;
Ok(()) Ok(())
} }
@ -150,7 +154,7 @@ impl UserSession {
Ok(user.into()) 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_id, token) = self.get_session()?.into_part();
let user = dsl::user_table let user = dsl::user_table
.filter(user_table::id.eq(&user_id)) .filter(user_table::id.eq(&user_id))
@ -179,27 +183,27 @@ impl UserSession {
} }
impl UserSession { impl UserSession {
fn read_user_profile_on_server(&self, token: &str) -> Result<(), FlowyError> { fn read_user_profile_on_server(&self, _token: &str) -> Result<(), FlowyError> {
let server = self.cloud_service.clone(); // let server = self.cloud_service.clone();
let token = token.to_owned(); // let token = token.to_owned();
tokio::spawn(async move { // tokio::spawn(async move {
match server.get_user(&token).await { // match server.get_user(&token).await {
Ok(profile) => { // Ok(profile) => {
dart_notify(&token, UserNotification::UserProfileUpdated) // dart_notify(&token, UserNotification::UserProfileUpdated)
.payload(profile) // .payload(profile)
.send(); // .send();
} // }
Err(e) => { // Err(e) => {
dart_notify(&token, UserNotification::UserProfileUpdated) // dart_notify(&token, UserNotification::UserProfileUpdated)
.error(e) // .error(e)
.send(); // .send();
} // }
} // }
}); // });
Ok(()) 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 server = self.cloud_service.clone();
let token = token.to_owned(); let token = token.to_owned();
let _ = tokio::spawn(async move { let _ = tokio::spawn(async move {
@ -275,7 +279,7 @@ impl UserSession {
pub async fn update_user( pub async fn update_user(
_cloud_service: Arc<dyn UserCloudService>, _cloud_service: Arc<dyn UserCloudService>,
pool: Arc<ConnectionPool>, pool: Arc<ConnectionPool>,
params: UpdateUserParams, params: UpdateUserProfileParams,
) -> Result<(), FlowyError> { ) -> Result<(), FlowyError> {
let changeset = UserTableChangeset::new(params); let changeset = UserTableChangeset::new(params);
let conn = pool.get()?; let conn = pool.get()?;

View File

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

View File

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