Browse Source

fix: update workspace setting

appflowy 3 years ago
parent
commit
448c134704

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

@@ -7,9 +7,7 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart';
 import 'package:app_flowy/workspace/application/trash/prelude.dart';
 import 'package:app_flowy/workspace/application/workspace/prelude.dart';
 import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
-import 'package:app_flowy/workspace/application/home/home_bloc.dart';
 import 'package:app_flowy/workspace/application/view/prelude.dart';
-import 'package:app_flowy/workspace/application/home/prelude.dart';
 import 'package:app_flowy/workspace/application/menu/prelude.dart';
 import 'package:app_flowy/user/application/prelude.dart';
 import 'package:app_flowy/user/presentation/router.dart';
@@ -45,7 +43,6 @@ void _resolveUserDeps(GetIt getIt) {
   getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthService>()));
 
   getIt.registerFactory<SplashRoute>(() => SplashRoute());
-  getIt.registerFactory<HomeBloc>(() => HomeBloc());
   getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
   getIt.registerFactory<SplashBloc>(() => SplashBloc());
   getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
@@ -58,10 +55,6 @@ void _resolveHomeDeps(GetIt getIt) {
     (user, _) => UserListener(user: user),
   );
 
-  getIt.registerFactoryParam<HomeListenBloc, UserProfile, void>(
-    (user, _) => HomeListenBloc(getIt<UserListener>(param1: user)),
-  );
-
   //
   getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
 

+ 54 - 18
frontend/app_flowy/lib/user/application/user_listener.dart

@@ -12,26 +12,55 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user;
 import 'package:flowy_sdk/rust_stream.dart';
 
-typedef UserProfileUpdatedNotifierValue = Either<UserProfile, FlowyError>;
-typedef AuthNotifierValue = Either<Unit, FlowyError>;
-typedef WorkspaceUpdatedNotifierValue = Either<List<Workspace>, FlowyError>;
+typedef UserProfileDidUpdate = Either<UserProfile, FlowyError>;
+typedef AuthDidUpdate = Either<Unit, FlowyError>;
+typedef WorkspaceListDidUpdate = Either<List<Workspace>, FlowyError>;
+typedef WorkspaceSettingDidUpdate = Either<CurrentWorkspaceSetting, FlowyError>;
 
 class UserListener {
   StreamSubscription<SubscribeObject>? _subscription;
-  final profileUpdatedNotifier = PublishNotifier<UserProfileUpdatedNotifierValue>();
-  final authDidChangedNotifier = PublishNotifier<AuthNotifierValue>();
-  final workspaceUpdatedNotifier = PublishNotifier<WorkspaceUpdatedNotifierValue>();
+  final _profileNotifier = PublishNotifier<UserProfileDidUpdate>();
+  final _authNotifier = PublishNotifier<AuthDidUpdate>();
+  final _workspaceListNotifier = PublishNotifier<WorkspaceListDidUpdate>();
+  final _workSettingNotifier = PublishNotifier<WorkspaceSettingDidUpdate>();
 
   FolderNotificationParser? _workspaceParser;
   UserNotificationParser? _userParser;
-  late UserProfile _user;
+  final UserProfile _user;
   UserListener({
     required UserProfile user,
+  }) : _user = user;
+
+  void start({
+    void Function(AuthDidUpdate)? authDidChange,
+    void Function(UserProfileDidUpdate)? profileDidUpdate,
+    void Function(WorkspaceListDidUpdate)? workspaceListDidUpdate,
+    void Function(WorkspaceSettingDidUpdate)? workspaceSettingDidUpdate,
   }) {
-    _user = user;
-  }
+    if (authDidChange != null) {
+      _authNotifier.addListener(() {
+        authDidChange(_authNotifier.currentValue!);
+      });
+    }
+
+    if (profileDidUpdate != null) {
+      _profileNotifier.addListener(() {
+        profileDidUpdate(_profileNotifier.currentValue!);
+      });
+    }
+
+    if (workspaceListDidUpdate != null) {
+      _workspaceListNotifier.addListener(() {
+        workspaceListDidUpdate(_workspaceListNotifier.currentValue!);
+      });
+    }
+
+    if (workspaceSettingDidUpdate != null) {
+      _workSettingNotifier.addListener(() {
+        workspaceSettingDidUpdate(_workSettingNotifier.currentValue!);
+      });
+    }
 
-  void start() {
     _workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback);
     _userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback);
     _subscription = RustStreamReceiver.listen((observable) {
@@ -44,9 +73,9 @@ class UserListener {
     _workspaceParser = null;
     _userParser = null;
     await _subscription?.cancel();
-    profileUpdatedNotifier.dispose();
-    authDidChangedNotifier.dispose();
-    workspaceUpdatedNotifier.dispose();
+    _profileNotifier.dispose();
+    _authNotifier.dispose();
+    _workspaceListNotifier.dispose();
   }
 
   void _notificationCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
@@ -55,16 +84,23 @@ class UserListener {
       case FolderNotification.UserDeleteWorkspace:
       case FolderNotification.WorkspaceListUpdated:
         result.fold(
-          (payload) => workspaceUpdatedNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items),
-          (error) => workspaceUpdatedNotifier.value = right(error),
+          (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) => authDidChangedNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
+          (error) => _authNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
         );
         break;
+
       default:
         break;
     }
@@ -74,8 +110,8 @@ class UserListener {
     switch (ty) {
       case user.UserNotification.UserUnauthorized:
         result.fold(
-          (payload) => profileUpdatedNotifier.value = left(UserProfile.fromBuffer(payload)),
-          (error) => profileUpdatedNotifier.value = right(error),
+          (payload) => _profileNotifier.value = left(UserProfile.fromBuffer(payload)),
+          (error) => _profileNotifier.value = right(error),
         );
         break;
       default:

+ 48 - 3
frontend/app_flowy/lib/workspace/application/home/home_bloc.dart

@@ -1,13 +1,36 @@
+import 'package:app_flowy/user/application/user_listener.dart';
 import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart';
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart' show CurrentWorkspaceSetting;
+import 'package:flowy_sdk/protobuf/flowy-user-data-model/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:dartz/dartz.dart';
 part 'home_bloc.freezed.dart';
 
 class HomeBloc extends Bloc<HomeEvent, HomeState> {
-  HomeBloc() : super(HomeState.initial()) {
+  final UserListener _listener;
+
+  HomeBloc(UserProfile user, CurrentWorkspaceSetting workspaceSetting)
+      : _listener = UserListener(user: user),
+        super(HomeState.initial(workspaceSetting)) {
     on<HomeEvent>((event, emit) async {
       await event.map(
+        initial: (_Initial value) {
+          _listener.start(
+            authDidChange: (result) {
+              _authDidChanged(result);
+            },
+            workspaceSettingDidUpdate: (result) {
+              result.fold(
+                (setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)),
+                (r) => Log.error(r),
+              );
+            },
+          );
+        },
         showLoading: (e) async {
           emit(state.copyWith(isLoading: e.isLoading));
         },
@@ -20,22 +43,40 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
         forceCollapse: (e) async {
           emit(state.copyWith(forceCollapse: e.forceCollapse));
         },
+        didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) {
+          emit(state.copyWith(workspaceSetting: value.setting));
+        },
+        unauthorized: (_Unauthorized value) {
+          emit(state.copyWith(unauthorized: true));
+        },
       );
     });
   }
 
   @override
-  Future<void> close() {
+  Future<void> close() async {
+    await _listener.stop();
     return super.close();
   }
+
+  void _authDidChanged(Either<Unit, FlowyError> errorOrNothing) {
+    errorOrNothing.fold((_) {}, (error) {
+      if (error.code == ErrorCode.UserUnauthorized.value) {
+        add(HomeEvent.unauthorized(error.msg));
+      }
+    });
+  }
 }
 
 @freezed
 class HomeEvent with _$HomeEvent {
+  const factory HomeEvent.initial() = _Initial;
   const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading;
   const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse;
   const factory HomeEvent.setEditPannel(EditPannelContext editContext) = _ShowEditPannel;
   const factory HomeEvent.dismissEditPannel() = _DismissEditPannel;
+  const factory HomeEvent.didReceiveWorkspaceSetting(CurrentWorkspaceSetting setting) = _DidReceiveWorkspaceSetting;
+  const factory HomeEvent.unauthorized(String msg) = _Unauthorized;
 }
 
 @freezed
@@ -44,11 +85,15 @@ class HomeState with _$HomeState {
     required bool isLoading,
     required bool forceCollapse,
     required Option<EditPannelContext> pannelContext,
+    required CurrentWorkspaceSetting workspaceSetting,
+    required bool unauthorized,
   }) = _HomeState;
 
-  factory HomeState.initial() => HomeState(
+  factory HomeState.initial(CurrentWorkspaceSetting workspaceSetting) => HomeState(
         isLoading: false,
         forceCollapse: false,
         pannelContext: none(),
+        workspaceSetting: workspaceSetting,
+        unauthorized: false,
       );
 }

+ 0 - 54
frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart

@@ -1,54 +0,0 @@
-import 'package:app_flowy/user/application/user_listener.dart';
-import 'package:flowy_sdk/protobuf/error-code/error_code.pbenum.dart';
-import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:dartz/dartz.dart';
-part 'home_listen_bloc.freezed.dart';
-
-class HomeListenBloc extends Bloc<HomeListenEvent, HomeListenState> {
-  final UserListener listener;
-  HomeListenBloc(this.listener) : super(const HomeListenState.loading()) {
-    on<HomeListenEvent>((event, emit) async {
-      await event.map(
-        started: (_) async {
-          listener.authDidChangedNotifier.addPublishListener((result) {
-            _authDidChanged(result);
-          });
-          listener.start();
-        },
-        stop: (_) async {},
-        unauthorized: (e) async {
-          emit(HomeListenState.unauthorized(e.msg));
-        },
-      );
-    });
-  }
-
-  @override
-  Future<void> close() async {
-    await listener.stop();
-    super.close();
-  }
-
-  void _authDidChanged(Either<Unit, FlowyError> errorOrNothing) {
-    errorOrNothing.fold((_) {}, (error) {
-      if (error.code == ErrorCode.UserUnauthorized.value) {
-        add(HomeListenEvent.unauthorized(error.msg));
-      }
-    });
-  }
-}
-
-@freezed
-class HomeListenEvent with _$HomeListenEvent {
-  const factory HomeListenEvent.started() = _Started;
-  const factory HomeListenEvent.stop() = _Stop;
-  const factory HomeListenEvent.unauthorized(String msg) = _Unauthorized;
-}
-
-@freezed
-class HomeListenState with _$HomeListenState {
-  const factory HomeListenState.loading() = Loading;
-  const factory HomeListenState.unauthorized(String msg) = Unauthorized;
-}

+ 1 - 1
frontend/app_flowy/lib/workspace/application/home/prelude.dart

@@ -1 +1 @@
-export 'home_listen_bloc.dart';
+

+ 5 - 4
frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart

@@ -19,9 +19,10 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
     on<MenuUserEvent>((event, emit) async {
       await event.map(
         initial: (_) async {
-          userListener.profileUpdatedNotifier.addPublishListener(_profileUpdated);
-          userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
-          userListener.start();
+          userListener.start(
+            profileDidUpdate: _profileUpdated,
+            workspaceListDidUpdate: _workspaceListUpdated,
+          );
           await _initUser();
         },
         fetchWorkspaces: (_FetchWorkspaces value) async {},
@@ -41,7 +42,7 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
   }
 
   void _profileUpdated(Either<UserProfile, FlowyError> userOrFailed) {}
-  void _workspacesUpdated(Either<List<Workspace>, FlowyError> workspacesOrFailed) {
+  void _workspaceListUpdated(Either<List<Workspace>, FlowyError> workspacesOrFailed) {
     // fetch workspaces
     // iUserImpl.fetchWorkspaces().then((result) {
     //   result.fold(

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

@@ -16,8 +16,9 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
     on<WelcomeEvent>(
       (event, emit) async {
         await event.map(initial: (e) async {
-          userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
-          userListener.start();
+          userListener.start(
+            workspaceListDidUpdate: (result) => add(WelcomeEvent.workspacesReveived(result)),
+          );
           //
           await _fetchWorkspaces(emit);
         }, openWorkspace: (e) async {
@@ -74,10 +75,6 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
       },
     ));
   }
-
-  void _workspacesUpdated(Either<List<Workspace>, FlowyError> workspacesOrFail) {
-    add(WelcomeEvent.workspacesReveived(workspacesOrFail));
-  }
 }
 
 @freezed

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

@@ -1,6 +1,5 @@
 import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/workspace/application/home/home_bloc.dart';
-import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart';
 import 'package:app_flowy/workspace/presentation/widgets/edit_pannel/pannel_animation.dart';
 import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart';
 import 'package:app_flowy/startup/startup.dart';
@@ -46,22 +45,20 @@ class _HomeScreenState extends State<HomeScreen> {
   Widget build(BuildContext context) {
     return MultiBlocProvider(
       providers: [
-        BlocProvider<HomeListenBloc>(
-          create: (context) => getIt<HomeListenBloc>(param1: widget.user)..add(const HomeListenEvent.started()),
+        BlocProvider<HomeBloc>(
+          create: (context) {
+            return HomeBloc(widget.user, widget.workspaceSetting)..add(const HomeEvent.initial());
+          },
         ),
-        BlocProvider<HomeBloc>(create: (context) => getIt<HomeBloc>()),
       ],
       child: Scaffold(
         key: HomeScreen.scaffoldKey,
-        body: BlocListener<HomeListenBloc, HomeListenState>(
+        body: BlocListener<HomeBloc, HomeState>(
+          listenWhen: (p, c) => p.unauthorized != c.unauthorized,
           listener: (context, state) {
-            state.map(
-              loading: (_) {},
-              unauthorized: (unauthorized) {
-                // TODO: push to login screen when user token was invalid
-                Log.error("Push to login screen when user token was invalid");
-              },
-            );
+            if (state.unauthorized) {
+              Log.error("Push to login screen when user token was invalid");
+            }
           },
           child: BlocBuilder<HomeBloc, HomeState>(
             buildWhen: (previous, current) => previous != current,
@@ -73,7 +70,7 @@ class _HomeScreenState extends State<HomeScreen> {
               return FlowyContainer(
                 Theme.of(context).colorScheme.surface,
                 // Colors.white,
-                child: _buildBody(state, context.read<HomeBloc>().state.forceCollapse),
+                child: _buildBody(state),
               );
             },
           ),
@@ -82,14 +79,15 @@ class _HomeScreenState extends State<HomeScreen> {
     );
   }
 
-  Widget _buildBody(HomeState state, bool forceCollapse) {
+  Widget _buildBody(HomeState state) {
     return LayoutBuilder(
       builder: (BuildContext context, BoxConstraints constraints) {
-        final layout = HomeLayout(context, constraints, forceCollapse);
+        final layout = HomeLayout(context, constraints, state.forceCollapse);
         const homeStack = HomeStack();
         final menu = _buildHomeMenu(
           layout: layout,
           context: context,
+          state: state,
         );
         final editPannel = _buildEditPannel(
           homeState: state,
@@ -108,20 +106,21 @@ class _HomeScreenState extends State<HomeScreen> {
     );
   }
 
-  Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context}) {
-    if (initialView == null && widget.workspaceSetting.hasLatestView()) {
-      initialView = widget.workspaceSetting.latestView;
+  Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context, required HomeState state}) {
+    final workspaceSetting = state.workspaceSetting;
+    if (initialView == null && workspaceSetting.hasLatestView()) {
+      initialView = workspaceSetting.latestView;
       final plugin = makePlugin(pluginType: initialView!.pluginType, data: initialView);
       getIt<HomeStackManager>().setPlugin(plugin);
     }
 
     HomeMenu homeMenu = HomeMenu(
       user: widget.user,
-      workspaceSetting: widget.workspaceSetting,
+      workspaceSetting: workspaceSetting,
       collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
     );
 
-    final latestView = widget.workspaceSetting.hasLatestView() ? widget.workspaceSetting.latestView : null;
+    final latestView = workspaceSetting.hasLatestView() ? workspaceSetting.latestView : null;
     getIt<MenuSharedState>().latestOpenView = latestView;
 
     return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));

+ 2 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbenum.dart

@@ -16,6 +16,7 @@ class FolderNotification extends $pb.ProtobufEnum {
   static const FolderNotification WorkspaceUpdated = FolderNotification._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceUpdated');
   static const FolderNotification WorkspaceListUpdated = FolderNotification._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceListUpdated');
   static const FolderNotification WorkspaceAppsChanged = FolderNotification._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceAppsChanged');
+  static const FolderNotification WorkspaceSetting = FolderNotification._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceSetting');
   static const FolderNotification AppUpdated = FolderNotification._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated');
   static const FolderNotification AppViewsChanged = FolderNotification._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppViewsChanged');
   static const FolderNotification ViewUpdated = FolderNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewUpdated');
@@ -31,6 +32,7 @@ class FolderNotification extends $pb.ProtobufEnum {
     WorkspaceUpdated,
     WorkspaceListUpdated,
     WorkspaceAppsChanged,
+    WorkspaceSetting,
     AppUpdated,
     AppViewsChanged,
     ViewUpdated,

+ 2 - 1
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbjson.dart

@@ -18,6 +18,7 @@ const FolderNotification$json = const {
     const {'1': 'WorkspaceUpdated', '2': 12},
     const {'1': 'WorkspaceListUpdated', '2': 13},
     const {'1': 'WorkspaceAppsChanged', '2': 14},
+    const {'1': 'WorkspaceSetting', '2': 15},
     const {'1': 'AppUpdated', '2': 21},
     const {'1': 'AppViewsChanged', '2': 24},
     const {'1': 'ViewUpdated', '2': 31},
@@ -29,4 +30,4 @@ const FolderNotification$json = const {
 };
 
 /// Descriptor for `FolderNotification`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List folderNotificationDescriptor = $convert.base64Decode('ChJGb2xkZXJOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIOCgpBcHBVcGRhdGVkEBUSEwoPQXBwVmlld3NDaGFuZ2VkEBgSDwoLVmlld1VwZGF0ZWQQHxIPCgtWaWV3RGVsZXRlZBAgEhAKDFZpZXdSZXN0b3JlZBAhEhQKEFVzZXJVbmF1dGhvcml6ZWQQZBIRCgxUcmFzaFVwZGF0ZWQQ6Ac=');
+final $typed_data.Uint8List folderNotificationDescriptor = $convert.base64Decode('ChJGb2xkZXJOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIUChBXb3Jrc3BhY2VTZXR0aW5nEA8SDgoKQXBwVXBkYXRlZBAVEhMKD0FwcFZpZXdzQ2hhbmdlZBAYEg8KC1ZpZXdVcGRhdGVkEB8SDwoLVmlld0RlbGV0ZWQQIBIQCgxWaWV3UmVzdG9yZWQQIRIUChBVc2VyVW5hdXRob3JpemVkEGQSEQoMVHJhc2hVcGRhdGVkEOgH');

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

@@ -10,6 +10,7 @@ pub(crate) enum FolderNotification {
     WorkspaceUpdated = 12,
     WorkspaceListUpdated = 13,
     WorkspaceAppsChanged = 14,
+    WorkspaceSetting = 15,
     AppUpdated = 21,
     AppViewsChanged = 24,
     ViewUpdated = 31,

+ 9 - 5
frontend/rust-lib/flowy-folder/src/protobuf/model/dart_notification.rs

@@ -31,6 +31,7 @@ pub enum FolderNotification {
     WorkspaceUpdated = 12,
     WorkspaceListUpdated = 13,
     WorkspaceAppsChanged = 14,
+    WorkspaceSetting = 15,
     AppUpdated = 21,
     AppViewsChanged = 24,
     ViewUpdated = 31,
@@ -53,6 +54,7 @@ impl ::protobuf::ProtobufEnum for FolderNotification {
             12 => ::std::option::Option::Some(FolderNotification::WorkspaceUpdated),
             13 => ::std::option::Option::Some(FolderNotification::WorkspaceListUpdated),
             14 => ::std::option::Option::Some(FolderNotification::WorkspaceAppsChanged),
+            15 => ::std::option::Option::Some(FolderNotification::WorkspaceSetting),
             21 => ::std::option::Option::Some(FolderNotification::AppUpdated),
             24 => ::std::option::Option::Some(FolderNotification::AppViewsChanged),
             31 => ::std::option::Option::Some(FolderNotification::ViewUpdated),
@@ -72,6 +74,7 @@ impl ::protobuf::ProtobufEnum for FolderNotification {
             FolderNotification::WorkspaceUpdated,
             FolderNotification::WorkspaceListUpdated,
             FolderNotification::WorkspaceAppsChanged,
+            FolderNotification::WorkspaceSetting,
             FolderNotification::AppUpdated,
             FolderNotification::AppViewsChanged,
             FolderNotification::ViewUpdated,
@@ -107,14 +110,15 @@ impl ::protobuf::reflect::ProtobufValue for FolderNotification {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x17dart_notification.proto*\x9f\x02\n\x12FolderNotification\x12\x0b\n\
+    \n\x17dart_notification.proto*\xb5\x02\n\x12FolderNotification\x12\x0b\n\
     \x07Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13Us\
     erDeleteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\
     \n\x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\
-    \x0e\x12\x0e\n\nAppUpdated\x10\x15\x12\x13\n\x0fAppViewsChanged\x10\x18\
-    \x12\x0f\n\x0bViewUpdated\x10\x1f\x12\x0f\n\x0bViewDeleted\x10\x20\x12\
-    \x10\n\x0cViewRestored\x10!\x12\x14\n\x10UserUnauthorized\x10d\x12\x11\n\
-    \x0cTrashUpdated\x10\xe8\x07b\x06proto3\
+    \x0e\x12\x14\n\x10WorkspaceSetting\x10\x0f\x12\x0e\n\nAppUpdated\x10\x15\
+    \x12\x13\n\x0fAppViewsChanged\x10\x18\x12\x0f\n\x0bViewUpdated\x10\x1f\
+    \x12\x0f\n\x0bViewDeleted\x10\x20\x12\x10\n\x0cViewRestored\x10!\x12\x14\
+    \n\x10UserUnauthorized\x10d\x12\x11\n\x0cTrashUpdated\x10\xe8\x07b\x06pr\
+    oto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 1 - 0
frontend/rust-lib/flowy-folder/src/protobuf/proto/dart_notification.proto

@@ -7,6 +7,7 @@ enum FolderNotification {
     WorkspaceUpdated = 12;
     WorkspaceListUpdated = 13;
     WorkspaceAppsChanged = 14;
+    WorkspaceSetting = 15;
     AppUpdated = 21;
     AppViewsChanged = 24;
     ViewUpdated = 31;

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

@@ -1,4 +1,5 @@
-use crate::services::AppController;
+use crate::manager::FolderManager;
+use crate::services::{notify_workspace_setting_did_change, AppController};
 use crate::{
     entities::{
         trash::Trash,
@@ -69,10 +70,12 @@ pub(crate) async fn delete_view_handler(
 
 pub(crate) async fn set_latest_view_handler(
     data: Data<ViewId>,
+    folder: AppData<Arc<FolderManager>>,
     controller: AppData<Arc<ViewController>>,
 ) -> Result<(), FlowyError> {
     let view_id: ViewId = data.into_inner();
     let _ = controller.set_latest_view(&view_id.value)?;
+    let _ = notify_workspace_setting_did_change(&folder, &view_id).await?;
     Ok(())
 }
 

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

@@ -1,3 +1,4 @@
+use crate::manager::FolderManager;
 use crate::{
     dart_notification::*,
     errors::*,
@@ -190,6 +191,44 @@ impl WorkspaceController {
     }
 }
 
+pub async fn notify_workspace_setting_did_change(
+    folder_manager: &Arc<FolderManager>,
+    view_id: &str,
+) -> FlowyResult<()> {
+    let user_id = folder_manager.user.user_id()?;
+    let token = folder_manager.user.token()?;
+    let workspace_id = get_current_workspace()?;
+
+    let workspace_setting = folder_manager
+        .persistence
+        .begin_transaction(|transaction| {
+            let workspace = folder_manager.workspace_controller.read_local_workspace(
+                workspace_id.clone(),
+                &user_id,
+                &transaction,
+            )?;
+
+            let setting = match transaction.read_view(view_id) {
+                Ok(latest_view) => CurrentWorkspaceSetting {
+                    workspace,
+                    latest_view: Some(latest_view),
+                },
+                Err(_) => CurrentWorkspaceSetting {
+                    workspace,
+                    latest_view: None,
+                },
+            };
+
+            Ok(setting)
+        })
+        .await?;
+
+    send_dart_notification(&token, FolderNotification::WorkspaceSetting)
+        .payload(workspace_setting)
+        .send();
+    Ok(())
+}
+
 const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
 
 pub fn set_current_workspace(workspace_id: &str) {

+ 8 - 0
shared-lib/flowy-folder-data-model/src/entities/view.rs

@@ -201,6 +201,14 @@ impl std::convert::From<&str> for ViewId {
     }
 }
 
+impl std::ops::Deref for ViewId {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        &self.value
+    }
+}
+
 #[derive(Default, ProtoBuf)]
 pub struct RepeatedViewId {
     #[pb(index = 1)]