ソースを参照

[flutter]: open latest view after launch

appflowy 3 年 前
コミット
d4353b2ee9
47 ファイル変更555 行追加952 行削除
  1. 2 1
      app_flowy/lib/user/domain/i_auth.dart
  2. 2 1
      app_flowy/lib/user/domain/i_splash.dart
  3. 3 2
      app_flowy/lib/user/infrastructure/i_auth_impl.dart
  4. 3 2
      app_flowy/lib/user/infrastructure/i_splash_impl.dart
  5. 4 3
      app_flowy/lib/user/presentation/skip_log_in_screen.dart
  6. 1 1
      app_flowy/lib/user/presentation/splash_screen.dart
  7. 11 3
      app_flowy/lib/workspace/presentation/home/home_screen.dart
  8. 2 3
      app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart
  9. 1 1
      app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart
  10. 1 1
      app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart
  11. 3 3
      app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart
  12. 1 2
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/protobuf.dart
  13. 0 105
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_delete.pb.dart
  14. 0 30
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_delete.pbjson.dart
  15. 92 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pb.dart
  16. 1 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbenum.dart
  17. 24 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbjson.dart
  18. 2 2
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbserver.dart
  19. 0 58
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pb.dart
  20. 0 7
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pbenum.dart
  21. 0 20
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pbjson.dart
  22. 0 9
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pbserver.dart
  23. 2 2
      backend/src/service/workspace/router.rs
  24. 2 2
      backend/tests/api/workspace.rs
  25. 1 1
      backend/tests/helper.rs
  26. 1 5
      rust-lib/flowy-backend-api/src/workspace_request.rs
  27. 2 3
      rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
  28. 3 3
      rust-lib/flowy-sdk/src/lib.rs
  29. 2 12
      rust-lib/flowy-workspace-infra/src/entities/workspace/mod.rs
  30. 0 25
      rust-lib/flowy-workspace-infra/src/entities/workspace/workspace_delete.rs
  31. 11 0
      rust-lib/flowy-workspace-infra/src/entities/workspace/workspace_setting.rs
  32. 0 7
      rust-lib/flowy-workspace-infra/src/entities/workspace/workspace_user_detail.rs
  33. 3 6
      rust-lib/flowy-workspace-infra/src/protobuf/model/mod.rs
  34. 0 369
      rust-lib/flowy-workspace-infra/src/protobuf/model/workspace_delete.rs
  35. 317 0
      rust-lib/flowy-workspace-infra/src/protobuf/model/workspace_setting.rs
  36. 0 205
      rust-lib/flowy-workspace-infra/src/protobuf/model/workspace_user_detail.rs
  37. 0 8
      rust-lib/flowy-workspace-infra/src/protobuf/proto/workspace_delete.proto
  38. 8 0
      rust-lib/flowy-workspace-infra/src/protobuf/proto/workspace_setting.proto
  39. 0 5
      rust-lib/flowy-workspace-infra/src/protobuf/proto/workspace_user_detail.proto
  40. 1 1
      rust-lib/flowy-workspace/Flowy.toml
  41. 2 2
      rust-lib/flowy-workspace/src/event.rs
  42. 1 1
      rust-lib/flowy-workspace/src/handlers/workspace_handler.rs
  43. 2 9
      rust-lib/flowy-workspace/src/services/server/mod.rs
  44. 2 9
      rust-lib/flowy-workspace/src/services/server/server_api.rs
  45. 2 9
      rust-lib/flowy-workspace/src/services/server/server_api_mock.rs
  46. 19 0
      rust-lib/flowy-workspace/src/services/view_controller.rs
  47. 21 13
      rust-lib/flowy-workspace/src/services/workspace_controller.rs

+ 2 - 1
app_flowy/lib/user/domain/i_auth.dart

@@ -1,5 +1,6 @@
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
 import 'package:flutter/material.dart';
 
 class NewUser {
@@ -21,5 +22,5 @@ abstract class IAuthRouter {
   void pushWelcomeScreen(BuildContext context, UserProfile userProfile);
   void pushSignUpScreen(BuildContext context);
   void pushForgetPasswordScreen(BuildContext context);
-  void pushHomeScreen(BuildContext context, UserProfile profile, String workspaceId);
+  void pushHomeScreen(BuildContext context, UserProfile profile, CurrentWorkspaceSetting workspaceSetting);
 }

+ 2 - 1
app_flowy/lib/user/domain/i_splash.dart

@@ -1,4 +1,5 @@
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
 import 'package:flutter/widgets.dart';
 
 import 'auth_state.dart';
@@ -20,5 +21,5 @@ abstract class ISplashRoute {
   void pushSkipLoginScreen(BuildContext context);
 
   Future<void> pushWelcomeScreen(BuildContext context, UserProfile profile);
-  void pushHomeScreen(BuildContext context, UserProfile profile, String workspaceId);
+  void pushHomeScreen(BuildContext context, UserProfile profile, CurrentWorkspaceSetting workspaceSetting);
 }

+ 3 - 2
app_flowy/lib/user/infrastructure/i_auth_impl.dart

@@ -8,6 +8,7 @@ import 'package:flowy_infra_ui/widget/route/animation.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
 import 'package:app_flowy/user/domain/i_auth.dart';
 import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
 import 'package:flutter/material.dart';
 
 class AuthImpl extends IAuth {
@@ -53,10 +54,10 @@ class AuthRouterImpl extends IAuthRouter {
   }
 
   @override
-  void pushHomeScreen(BuildContext context, UserProfile profile, String workspaceId) {
+  void pushHomeScreen(BuildContext context, UserProfile profile, CurrentWorkspaceSetting workspaceSetting) {
     Navigator.push(
       context,
-      PageRoutes.fade(() => HomeScreen(profile, workspaceId), RouteDurations.slow.inMilliseconds * .001),
+      PageRoutes.fade(() => HomeScreen(profile, workspaceSetting), RouteDurations.slow.inMilliseconds * .001),
     );
   }
 }

+ 3 - 2
app_flowy/lib/user/infrastructure/i_splash_impl.dart

@@ -11,6 +11,7 @@ import 'package:flowy_infra/time/duration.dart';
 import 'package:flowy_infra_ui/widget/route/animation.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 
@@ -47,10 +48,10 @@ class SplashRoute implements ISplashRoute {
   }
 
   @override
-  void pushHomeScreen(BuildContext context, UserProfile userProfile, String workspaceId) {
+  void pushHomeScreen(BuildContext context, UserProfile userProfile, CurrentWorkspaceSetting workspaceSetting) {
     Navigator.push(
       context,
-      PageRoutes.fade(() => HomeScreen(userProfile, workspaceId), RouteDurations.slow.inMilliseconds * .001),
+      PageRoutes.fade(() => HomeScreen(userProfile, workspaceSetting), RouteDurations.slow.inMilliseconds * .001),
     );
   }
 

+ 4 - 3
app_flowy/lib/user/presentation/skip_log_in_screen.dart

@@ -9,6 +9,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_log/flowy_log.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
 import 'package:flutter/material.dart';
@@ -112,11 +113,11 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
   void _openCurrentWorkspace(
     BuildContext context,
     UserProfile user,
-    dartz.Either<Workspace, WorkspaceError> workspacesOrError,
+    dartz.Either<CurrentWorkspaceSetting, WorkspaceError> workspacesOrError,
   ) {
     workspacesOrError.fold(
-      (workspace) {
-        widget.router.pushHomeScreen(context, user, workspace.id);
+      (workspaceSetting) {
+        widget.router.pushHomeScreen(context, user, workspaceSetting);
       },
       (error) {
         Log.error(error);

+ 1 - 1
app_flowy/lib/user/presentation/splash_screen.dart

@@ -47,7 +47,7 @@ class SplashScreen extends StatelessWidget {
     WorkspaceEventReadCurWorkspace().send().then(
       (result) {
         return result.fold(
-          (workspace) => getIt<ISplashRoute>().pushHomeScreen(context, userProfile, workspace.id),
+          (workspaceSetting) => getIt<ISplashRoute>().pushHomeScreen(context, userProfile, workspaceSetting),
           (error) async {
             assert(error.code == ErrorCode.RecordNotFound.value);
             getIt<ISplashRoute>().pushWelcomeScreen(context, userProfile);

+ 11 - 3
app_flowy/lib/workspace/presentation/home/home_screen.dart

@@ -1,6 +1,7 @@
 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/domain/page_stack/page_stack.dart';
+import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart';
 import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart';
 import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
@@ -8,17 +9,19 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:flowy_log/flowy_log.dart';
 import 'package:flowy_infra_ui/style_widget/container.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';
+import 'package:app_flowy/workspace/domain/view_ext.dart';
 
 import 'home_layout.dart';
 
 class HomeScreen extends StatelessWidget {
   static GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
   final UserProfile user;
-  final String workspaceId;
-  const HomeScreen(this.user, this.workspaceId, {Key? key}) : super(key: key);
+  final CurrentWorkspaceSetting workspaceSetting;
+  const HomeScreen(this.user, this.workspaceSetting, {Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -86,7 +89,8 @@ class HomeScreen extends StatelessWidget {
     final homeBloc = context.read<HomeBloc>();
     final collapasedNotifier = getIt<HomeStackManager>().collapsedNotifier;
 
-    HomeMenu homeMenu = HomeMenu(user: user, workspaceId: workspaceId, collapsedNotifier: collapasedNotifier);
+    HomeMenu homeMenu =
+        HomeMenu(user: user, workspaceId: workspaceSetting.workspace.id, collapsedNotifier: collapasedNotifier);
     collapasedNotifier.addPublishListener((isCollapsed) {
       homeBloc.add(HomeEvent.forceCollapse(isCollapsed));
     });
@@ -95,6 +99,10 @@ class HomeScreen extends StatelessWidget {
       getIt<HomeStackManager>().switchStack(pageContext);
     });
 
+    if (workspaceSetting.hasLatestView()) {
+      getIt<HomeStackManager>().switchStack(workspaceSetting.latestView.stackContext());
+    }
+
     return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
   }
 

+ 2 - 3
app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart

@@ -80,7 +80,7 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
 class DocLeftBarItem extends StatefulWidget {
   final View view;
 
-  const DocLeftBarItem({required this.view, Key? key}) : super(key: key);
+  DocLeftBarItem({required this.view, Key? key}) : super(key: ValueKey(view.hashCode));
 
   @override
   State<DocLeftBarItem> createState() => _DocLeftBarItemState();
@@ -95,7 +95,6 @@ class _DocLeftBarItemState extends State<DocLeftBarItem> {
   void initState() {
     repo = ViewRepository(view: widget.view);
     _focusNode.addListener(_handleFocusChanged);
-
     super.initState();
   }
 
@@ -147,7 +146,7 @@ class _DocLeftBarItemState extends State<DocLeftBarItem> {
 
 class DocShareButton extends StatelessWidget {
   final View view;
-  DocShareButton({Key? key, required this.view}) : super(key: ValueKey(view.id));
+  DocShareButton({Key? key, required this.view}) : super(key: ValueKey(view.hashCode));
 
   @override
   Widget build(BuildContext context) {

+ 1 - 1
app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart

@@ -13,7 +13,7 @@ import 'section/section.dart';
 
 class MenuApp extends StatefulWidget {
   final App app;
-  MenuApp(this.app, {Key? key}) : super(key: ValueKey("${app.id}${app.version}"));
+  MenuApp(this.app, {Key? key}) : super(key: ValueKey(app.hashCode));
 
   @override
   State<MenuApp> createState() => _MenuAppState();

+ 1 - 1
app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart

@@ -28,7 +28,7 @@ class ViewSectionItem extends StatelessWidget {
     required this.view,
     required this.isSelected,
     required this.onSelected,
-  }) : super(key: ValueKey('$view.id/$isSelected'));
+  }) : super(key: ValueKey(view.hashCode));
 
   @override
   Widget build(BuildContext context) {

+ 3 - 3
app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart

@@ -22,12 +22,12 @@ class WorkspaceEventCreateWorkspace {
 class WorkspaceEventReadCurWorkspace {
     WorkspaceEventReadCurWorkspace();
 
-    Future<Either<Workspace, WorkspaceError>> send() {
+    Future<Either<CurrentWorkspaceSetting, WorkspaceError>> send() {
      final request = FFIRequest.create()
         ..event = WorkspaceEvent.ReadCurWorkspace.toString();
 
      return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
-        (okBytes) => left(Workspace.fromBuffer(okBytes)),
+        (okBytes) => left(CurrentWorkspaceSetting.fromBuffer(okBytes)),
         (errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
       ));
     }
@@ -51,7 +51,7 @@ class WorkspaceEventReadWorkspaces {
 }
 
 class WorkspaceEventDeleteWorkspace {
-     DeleteWorkspaceRequest request;
+     QueryWorkspaceRequest request;
      WorkspaceEventDeleteWorkspace(this.request);
 
     Future<Either<Unit, WorkspaceError>> send() {

+ 1 - 2
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/protobuf.dart

@@ -1,13 +1,12 @@
 // Auto-generated, do not edit 
 export './view_update.pb.dart';
+export './workspace_setting.pb.dart';
 export './app_query.pb.dart';
-export './workspace_delete.pb.dart';
 export './errors.pb.dart';
 export './workspace_update.pb.dart';
 export './app_create.pb.dart';
 export './workspace_query.pb.dart';
 export './view_create.pb.dart';
-export './workspace_user_detail.pb.dart';
 export './workspace_create.pb.dart';
 export './app_update.pb.dart';
 export './view_query.pb.dart';

+ 0 - 105
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_delete.pb.dart

@@ -1,105 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: workspace_delete.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
-
-import 'dart:core' as $core;
-
-import 'package:protobuf/protobuf.dart' as $pb;
-
-class DeleteWorkspaceRequest extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteWorkspaceRequest', createEmptyInstance: create)
-    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspaceId')
-    ..hasRequiredFields = false
-  ;
-
-  DeleteWorkspaceRequest._() : super();
-  factory DeleteWorkspaceRequest({
-    $core.String? workspaceId,
-  }) {
-    final _result = create();
-    if (workspaceId != null) {
-      _result.workspaceId = workspaceId;
-    }
-    return _result;
-  }
-  factory DeleteWorkspaceRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory DeleteWorkspaceRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-  'Will be removed in next major version')
-  DeleteWorkspaceRequest clone() => DeleteWorkspaceRequest()..mergeFromMessage(this);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-  'Will be removed in next major version')
-  DeleteWorkspaceRequest copyWith(void Function(DeleteWorkspaceRequest) updates) => super.copyWith((message) => updates(message as DeleteWorkspaceRequest)) as DeleteWorkspaceRequest; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static DeleteWorkspaceRequest create() => DeleteWorkspaceRequest._();
-  DeleteWorkspaceRequest createEmptyInstance() => create();
-  static $pb.PbList<DeleteWorkspaceRequest> createRepeated() => $pb.PbList<DeleteWorkspaceRequest>();
-  @$core.pragma('dart2js:noInline')
-  static DeleteWorkspaceRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DeleteWorkspaceRequest>(create);
-  static DeleteWorkspaceRequest? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.String get workspaceId => $_getSZ(0);
-  @$pb.TagNumber(1)
-  set workspaceId($core.String v) { $_setString(0, v); }
-  @$pb.TagNumber(1)
-  $core.bool hasWorkspaceId() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearWorkspaceId() => clearField(1);
-}
-
-class DeleteWorkspaceParams extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteWorkspaceParams', createEmptyInstance: create)
-    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspaceId')
-    ..hasRequiredFields = false
-  ;
-
-  DeleteWorkspaceParams._() : super();
-  factory DeleteWorkspaceParams({
-    $core.String? workspaceId,
-  }) {
-    final _result = create();
-    if (workspaceId != null) {
-      _result.workspaceId = workspaceId;
-    }
-    return _result;
-  }
-  factory DeleteWorkspaceParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory DeleteWorkspaceParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-  'Will be removed in next major version')
-  DeleteWorkspaceParams clone() => DeleteWorkspaceParams()..mergeFromMessage(this);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-  'Will be removed in next major version')
-  DeleteWorkspaceParams copyWith(void Function(DeleteWorkspaceParams) updates) => super.copyWith((message) => updates(message as DeleteWorkspaceParams)) as DeleteWorkspaceParams; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static DeleteWorkspaceParams create() => DeleteWorkspaceParams._();
-  DeleteWorkspaceParams createEmptyInstance() => create();
-  static $pb.PbList<DeleteWorkspaceParams> createRepeated() => $pb.PbList<DeleteWorkspaceParams>();
-  @$core.pragma('dart2js:noInline')
-  static DeleteWorkspaceParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DeleteWorkspaceParams>(create);
-  static DeleteWorkspaceParams? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.String get workspaceId => $_getSZ(0);
-  @$pb.TagNumber(1)
-  set workspaceId($core.String v) { $_setString(0, v); }
-  @$pb.TagNumber(1)
-  $core.bool hasWorkspaceId() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearWorkspaceId() => clearField(1);
-}
-

+ 0 - 30
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_delete.pbjson.dart

@@ -1,30 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: workspace_delete.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
-
-import 'dart:core' as $core;
-import 'dart:convert' as $convert;
-import 'dart:typed_data' as $typed_data;
-@$core.Deprecated('Use deleteWorkspaceRequestDescriptor instead')
-const DeleteWorkspaceRequest$json = const {
-  '1': 'DeleteWorkspaceRequest',
-  '2': const [
-    const {'1': 'workspace_id', '3': 1, '4': 1, '5': 9, '10': 'workspaceId'},
-  ],
-};
-
-/// Descriptor for `DeleteWorkspaceRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List deleteWorkspaceRequestDescriptor = $convert.base64Decode('ChZEZWxldGVXb3Jrc3BhY2VSZXF1ZXN0EiEKDHdvcmtzcGFjZV9pZBgBIAEoCVILd29ya3NwYWNlSWQ=');
-@$core.Deprecated('Use deleteWorkspaceParamsDescriptor instead')
-const DeleteWorkspaceParams$json = const {
-  '1': 'DeleteWorkspaceParams',
-  '2': const [
-    const {'1': 'workspace_id', '3': 1, '4': 1, '5': 9, '10': 'workspaceId'},
-  ],
-};
-
-/// Descriptor for `DeleteWorkspaceParams`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List deleteWorkspaceParamsDescriptor = $convert.base64Decode('ChVEZWxldGVXb3Jrc3BhY2VQYXJhbXMSIQoMd29ya3NwYWNlX2lkGAEgASgJUgt3b3Jrc3BhY2VJZA==');

+ 92 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pb.dart

@@ -0,0 +1,92 @@
+///
+//  Generated code. Do not modify.
+//  source: workspace_setting.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+import 'workspace_create.pb.dart' as $0;
+import 'view_create.pb.dart' as $1;
+
+enum CurrentWorkspaceSetting_OneOfLatestView {
+  latestView, 
+  notSet
+}
+
+class CurrentWorkspaceSetting extends $pb.GeneratedMessage {
+  static const $core.Map<$core.int, CurrentWorkspaceSetting_OneOfLatestView> _CurrentWorkspaceSetting_OneOfLatestViewByTag = {
+    2 : CurrentWorkspaceSetting_OneOfLatestView.latestView,
+    0 : CurrentWorkspaceSetting_OneOfLatestView.notSet
+  };
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CurrentWorkspaceSetting', createEmptyInstance: create)
+    ..oo(0, [2])
+    ..aOM<$0.Workspace>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspace', subBuilder: $0.Workspace.create)
+    ..aOM<$1.View>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'latestView', subBuilder: $1.View.create)
+    ..hasRequiredFields = false
+  ;
+
+  CurrentWorkspaceSetting._() : super();
+  factory CurrentWorkspaceSetting({
+    $0.Workspace? workspace,
+    $1.View? latestView,
+  }) {
+    final _result = create();
+    if (workspace != null) {
+      _result.workspace = workspace;
+    }
+    if (latestView != null) {
+      _result.latestView = latestView;
+    }
+    return _result;
+  }
+  factory CurrentWorkspaceSetting.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory CurrentWorkspaceSetting.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+  'Will be removed in next major version')
+  CurrentWorkspaceSetting clone() => CurrentWorkspaceSetting()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  CurrentWorkspaceSetting copyWith(void Function(CurrentWorkspaceSetting) updates) => super.copyWith((message) => updates(message as CurrentWorkspaceSetting)) as CurrentWorkspaceSetting; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static CurrentWorkspaceSetting create() => CurrentWorkspaceSetting._();
+  CurrentWorkspaceSetting createEmptyInstance() => create();
+  static $pb.PbList<CurrentWorkspaceSetting> createRepeated() => $pb.PbList<CurrentWorkspaceSetting>();
+  @$core.pragma('dart2js:noInline')
+  static CurrentWorkspaceSetting getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CurrentWorkspaceSetting>(create);
+  static CurrentWorkspaceSetting? _defaultInstance;
+
+  CurrentWorkspaceSetting_OneOfLatestView whichOneOfLatestView() => _CurrentWorkspaceSetting_OneOfLatestViewByTag[$_whichOneof(0)]!;
+  void clearOneOfLatestView() => clearField($_whichOneof(0));
+
+  @$pb.TagNumber(1)
+  $0.Workspace get workspace => $_getN(0);
+  @$pb.TagNumber(1)
+  set workspace($0.Workspace v) { setField(1, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasWorkspace() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearWorkspace() => clearField(1);
+  @$pb.TagNumber(1)
+  $0.Workspace ensureWorkspace() => $_ensure(0);
+
+  @$pb.TagNumber(2)
+  $1.View get latestView => $_getN(1);
+  @$pb.TagNumber(2)
+  set latestView($1.View v) { setField(2, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasLatestView() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearLatestView() => clearField(2);
+  @$pb.TagNumber(2)
+  $1.View ensureLatestView() => $_ensure(1);
+}
+

+ 1 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_delete.pbenum.dart → app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbenum.dart

@@ -1,6 +1,6 @@
 ///
 //  Generated code. Do not modify.
-//  source: workspace_delete.proto
+//  source: workspace_setting.proto
 //
 // @dart = 2.12
 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields

+ 24 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbjson.dart

@@ -0,0 +1,24 @@
+///
+//  Generated code. Do not modify.
+//  source: workspace_setting.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use currentWorkspaceSettingDescriptor instead')
+const CurrentWorkspaceSetting$json = const {
+  '1': 'CurrentWorkspaceSetting',
+  '2': const [
+    const {'1': 'workspace', '3': 1, '4': 1, '5': 11, '6': '.Workspace', '10': 'workspace'},
+    const {'1': 'latest_view', '3': 2, '4': 1, '5': 11, '6': '.View', '9': 0, '10': 'latestView'},
+  ],
+  '8': const [
+    const {'1': 'one_of_latest_view'},
+  ],
+};
+
+/// Descriptor for `CurrentWorkspaceSetting`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List currentWorkspaceSettingDescriptor = $convert.base64Decode('ChdDdXJyZW50V29ya3NwYWNlU2V0dGluZxIoCgl3b3Jrc3BhY2UYASABKAsyCi5Xb3Jrc3BhY2VSCXdvcmtzcGFjZRIoCgtsYXRlc3RfdmlldxgCIAEoCzIFLlZpZXdIAFIKbGF0ZXN0Vmlld0IUChJvbmVfb2ZfbGF0ZXN0X3ZpZXc=');

+ 2 - 2
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_delete.pbserver.dart → app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbserver.dart

@@ -1,9 +1,9 @@
 ///
 //  Generated code. Do not modify.
-//  source: workspace_delete.proto
+//  source: workspace_setting.proto
 //
 // @dart = 2.12
 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
 
-export 'workspace_delete.pb.dart';
+export 'workspace_setting.pb.dart';
 

+ 0 - 58
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pb.dart

@@ -1,58 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: workspace_user_detail.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
-
-import 'dart:core' as $core;
-
-import 'package:protobuf/protobuf.dart' as $pb;
-
-class CurrentWorkspace extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CurrentWorkspace', createEmptyInstance: create)
-    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspaceId')
-    ..hasRequiredFields = false
-  ;
-
-  CurrentWorkspace._() : super();
-  factory CurrentWorkspace({
-    $core.String? workspaceId,
-  }) {
-    final _result = create();
-    if (workspaceId != null) {
-      _result.workspaceId = workspaceId;
-    }
-    return _result;
-  }
-  factory CurrentWorkspace.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory CurrentWorkspace.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-  'Will be removed in next major version')
-  CurrentWorkspace clone() => CurrentWorkspace()..mergeFromMessage(this);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-  'Will be removed in next major version')
-  CurrentWorkspace copyWith(void Function(CurrentWorkspace) updates) => super.copyWith((message) => updates(message as CurrentWorkspace)) as CurrentWorkspace; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static CurrentWorkspace create() => CurrentWorkspace._();
-  CurrentWorkspace createEmptyInstance() => create();
-  static $pb.PbList<CurrentWorkspace> createRepeated() => $pb.PbList<CurrentWorkspace>();
-  @$core.pragma('dart2js:noInline')
-  static CurrentWorkspace getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CurrentWorkspace>(create);
-  static CurrentWorkspace? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.String get workspaceId => $_getSZ(0);
-  @$pb.TagNumber(1)
-  set workspaceId($core.String v) { $_setString(0, v); }
-  @$pb.TagNumber(1)
-  $core.bool hasWorkspaceId() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearWorkspaceId() => clearField(1);
-}
-

+ 0 - 7
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pbenum.dart

@@ -1,7 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: workspace_user_detail.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
-

+ 0 - 20
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pbjson.dart

@@ -1,20 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: workspace_user_detail.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
-
-import 'dart:core' as $core;
-import 'dart:convert' as $convert;
-import 'dart:typed_data' as $typed_data;
-@$core.Deprecated('Use currentWorkspaceDescriptor instead')
-const CurrentWorkspace$json = const {
-  '1': 'CurrentWorkspace',
-  '2': const [
-    const {'1': 'workspace_id', '3': 1, '4': 1, '5': 9, '10': 'workspaceId'},
-  ],
-};
-
-/// Descriptor for `CurrentWorkspace`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List currentWorkspaceDescriptor = $convert.base64Decode('ChBDdXJyZW50V29ya3NwYWNlEiEKDHdvcmtzcGFjZV9pZBgBIAEoCVILd29ya3NwYWNlSWQ=');

+ 0 - 9
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_user_detail.pbserver.dart

@@ -1,9 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: workspace_user_detail.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
-
-export 'workspace_user_detail.pb.dart';
-

+ 2 - 2
backend/src/service/workspace/router.rs

@@ -20,7 +20,7 @@ use flowy_net::{
 };
 use flowy_workspace_infra::{
     parser::workspace::{WorkspaceDesc, WorkspaceName},
-    protobuf::{CreateWorkspaceParams, DeleteWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdentifier},
+    protobuf::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdentifier},
 };
 use sqlx::PgPool;
 
@@ -76,7 +76,7 @@ pub async fn delete_handler(
     pool: Data<PgPool>,
     _logged_user: LoggedUser,
 ) -> Result<HttpResponse, ServerError> {
-    let params: DeleteWorkspaceParams = parse_from_payload(payload).await?;
+    let params: WorkspaceIdentifier = parse_from_payload(payload).await?;
     let workspace_id = check_workspace_id(params.get_workspace_id().to_owned())?;
     let mut transaction = pool
         .begin()

+ 2 - 2
backend/tests/api/workspace.rs

@@ -3,7 +3,7 @@ use flowy_workspace_infra::entities::{
     app::{AppIdentifier, UpdateAppParams},
     trash::{TrashIdentifier, TrashIdentifiers, TrashType},
     view::{UpdateViewParams, ViewIdentifier},
-    workspace::{CreateWorkspaceParams, DeleteWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdentifier},
+    workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdentifier},
 };
 
 #[actix_rt::test]
@@ -57,7 +57,7 @@ async fn workspace_update() {
 #[actix_rt::test]
 async fn workspace_delete() {
     let test = WorkspaceTest::new().await;
-    let delete_params = DeleteWorkspaceParams {
+    let delete_params = WorkspaceIdentifier {
         workspace_id: test.workspace.id.clone(),
     };
 

+ 1 - 1
backend/tests/helper.rs

@@ -77,7 +77,7 @@ impl TestUserServer {
         update_workspace_request(self.user_token(), params, &url).await.unwrap();
     }
 
-    pub async fn delete_workspace(&self, params: DeleteWorkspaceParams) {
+    pub async fn delete_workspace(&self, params: WorkspaceIdentifier) {
         let url = format!("{}/api/workspace", self.http_addr());
         delete_workspace_request(self.user_token(), params, &url).await.unwrap();
     }

+ 1 - 5
rust-lib/flowy-backend-api/src/workspace_request.rs

@@ -48,11 +48,7 @@ pub async fn update_workspace_request(
     Ok(())
 }
 
-pub async fn delete_workspace_request(
-    token: &str,
-    params: DeleteWorkspaceParams,
-    url: &str,
-) -> Result<(), ServerError> {
+pub async fn delete_workspace_request(token: &str, params: WorkspaceIdentifier, url: &str) -> Result<(), ServerError> {
     let _ = request_builder()
         .delete(url)
         .header(HEADER_TOKEN, token)

+ 2 - 3
rust-lib/flowy-derive/src/derive_cache/derive_cache.rs

@@ -26,15 +26,13 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "UpdateAppParams"
         | "UpdateWorkspaceRequest"
         | "UpdateWorkspaceParams"
-        | "DeleteWorkspaceRequest"
-        | "DeleteWorkspaceParams"
+        | "CurrentWorkspaceSetting"
         | "CreateWorkspaceRequest"
         | "CreateWorkspaceParams"
         | "Workspace"
         | "RepeatedWorkspace"
         | "QueryWorkspaceRequest"
         | "WorkspaceIdentifier"
-        | "CurrentWorkspace"
         | "TrashIdentifiers"
         | "TrashIdentifier"
         | "Trash"
@@ -85,6 +83,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "ExportType"
         | "ErrorCode"
         | "WorkspaceEvent"
+        | "WorkspaceNotification"
         | "WsModule"
         | "RevType"
         | "WsDataType"

+ 3 - 3
rust-lib/flowy-sdk/src/lib.rs

@@ -114,13 +114,13 @@ async fn _listen_user_status(
                 let result = || async {
                     match status {
                         UserStatus::Login { token } => {
-                            let _ = workspace_controller.user_did_sign_in(&token)?;
+                            let _ = workspace_controller.user_did_sign_in(&token).await?;
                         },
                         UserStatus::Logout { .. } => {
-                            workspace_controller.user_did_logout();
+                            workspace_controller.user_did_logout().await;
                         },
                         UserStatus::Expired { .. } => {
-                            workspace_controller.user_session_expired();
+                            workspace_controller.user_session_expired().await;
                         },
                         UserStatus::SignUp { profile, ret } => {
                             let _ = workspace_controller.user_did_sign_up(&profile.token).await?;

+ 2 - 12
rust-lib/flowy-workspace-infra/src/entities/workspace/mod.rs

@@ -1,19 +1,9 @@
 pub use workspace_create::*;
-
-pub use workspace_delete::*;
-
 pub use workspace_query::*;
-
+pub use workspace_setting::*;
 pub use workspace_update::*;
 
-pub use workspace_user_detail::*;
-
 mod workspace_create;
-
-mod workspace_delete;
-
 mod workspace_query;
-
+mod workspace_setting;
 mod workspace_update;
-
-mod workspace_user_detail;

+ 0 - 25
rust-lib/flowy-workspace-infra/src/entities/workspace/workspace_delete.rs

@@ -1,25 +0,0 @@
-use crate::{errors::ErrorCode, parser::workspace::WorkspaceId};
-use flowy_derive::ProtoBuf;
-use std::convert::TryInto;
-
-#[derive(Default, ProtoBuf)]
-pub struct DeleteWorkspaceRequest {
-    #[pb(index = 1)]
-    workspace_id: String,
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct DeleteWorkspaceParams {
-    #[pb(index = 1)]
-    pub workspace_id: String,
-}
-
-impl TryInto<DeleteWorkspaceParams> for DeleteWorkspaceRequest {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<DeleteWorkspaceParams, Self::Error> {
-        let workspace_id = WorkspaceId::parse(self.workspace_id)?.0;
-
-        Ok(DeleteWorkspaceParams { workspace_id })
-    }
-}

+ 11 - 0
rust-lib/flowy-workspace-infra/src/entities/workspace/workspace_setting.rs

@@ -0,0 +1,11 @@
+use crate::entities::{view::View, workspace::Workspace};
+use flowy_derive::ProtoBuf;
+
+#[derive(Default, ProtoBuf, Clone)]
+pub struct CurrentWorkspaceSetting {
+    #[pb(index = 1)]
+    pub workspace: Workspace,
+
+    #[pb(index = 2, one_of)]
+    pub latest_view: Option<View>,
+}

+ 0 - 7
rust-lib/flowy-workspace-infra/src/entities/workspace/workspace_user_detail.rs

@@ -1,7 +0,0 @@
-use flowy_derive::ProtoBuf;
-
-#[derive(ProtoBuf, Default, Debug)]
-pub struct CurrentWorkspace {
-    #[pb(index = 1)]
-    pub workspace_id: String,
-}

+ 3 - 6
rust-lib/flowy-workspace-infra/src/protobuf/model/mod.rs

@@ -3,12 +3,12 @@
 mod view_update; 
 pub use view_update::*; 
 
+mod workspace_setting; 
+pub use workspace_setting::*; 
+
 mod app_query; 
 pub use app_query::*; 
 
-mod workspace_delete; 
-pub use workspace_delete::*; 
-
 mod errors; 
 pub use errors::*; 
 
@@ -24,9 +24,6 @@ pub use workspace_query::*;
 mod view_create; 
 pub use view_create::*; 
 
-mod workspace_user_detail; 
-pub use workspace_user_detail::*; 
-
 mod workspace_create; 
 pub use workspace_create::*; 
 

+ 0 - 369
rust-lib/flowy-workspace-infra/src/protobuf/model/workspace_delete.rs

@@ -1,369 +0,0 @@
-// This file is generated by rust-protobuf 2.22.1. Do not edit
-// @generated
-
-// https://github.com/rust-lang/rust-clippy/issues/702
-#![allow(unknown_lints)]
-#![allow(clippy::all)]
-
-#![allow(unused_attributes)]
-#![cfg_attr(rustfmt, rustfmt::skip)]
-
-#![allow(box_pointers)]
-#![allow(dead_code)]
-#![allow(missing_docs)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-#![allow(non_upper_case_globals)]
-#![allow(trivial_casts)]
-#![allow(unused_imports)]
-#![allow(unused_results)]
-//! Generated file from `workspace_delete.proto`
-
-/// Generated files are compatible only with the same version
-/// of protobuf runtime.
-// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
-
-#[derive(PartialEq,Clone,Default)]
-pub struct DeleteWorkspaceRequest {
-    // message fields
-    pub workspace_id: ::std::string::String,
-    // special fields
-    pub unknown_fields: ::protobuf::UnknownFields,
-    pub cached_size: ::protobuf::CachedSize,
-}
-
-impl<'a> ::std::default::Default for &'a DeleteWorkspaceRequest {
-    fn default() -> &'a DeleteWorkspaceRequest {
-        <DeleteWorkspaceRequest as ::protobuf::Message>::default_instance()
-    }
-}
-
-impl DeleteWorkspaceRequest {
-    pub fn new() -> DeleteWorkspaceRequest {
-        ::std::default::Default::default()
-    }
-
-    // string workspace_id = 1;
-
-
-    pub fn get_workspace_id(&self) -> &str {
-        &self.workspace_id
-    }
-    pub fn clear_workspace_id(&mut self) {
-        self.workspace_id.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_workspace_id(&mut self, v: ::std::string::String) {
-        self.workspace_id = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_workspace_id(&mut self) -> &mut ::std::string::String {
-        &mut self.workspace_id
-    }
-
-    // Take field
-    pub fn take_workspace_id(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.workspace_id, ::std::string::String::new())
-    }
-}
-
-impl ::protobuf::Message for DeleteWorkspaceRequest {
-    fn is_initialized(&self) -> bool {
-        true
-    }
-
-    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        while !is.eof()? {
-            let (field_number, wire_type) = is.read_tag_unpack()?;
-            match field_number {
-                1 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.workspace_id)?;
-                },
-                _ => {
-                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
-                },
-            };
-        }
-        ::std::result::Result::Ok(())
-    }
-
-    // Compute sizes of nested messages
-    #[allow(unused_variables)]
-    fn compute_size(&self) -> u32 {
-        let mut my_size = 0;
-        if !self.workspace_id.is_empty() {
-            my_size += ::protobuf::rt::string_size(1, &self.workspace_id);
-        }
-        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
-        self.cached_size.set(my_size);
-        my_size
-    }
-
-    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if !self.workspace_id.is_empty() {
-            os.write_string(1, &self.workspace_id)?;
-        }
-        os.write_unknown_fields(self.get_unknown_fields())?;
-        ::std::result::Result::Ok(())
-    }
-
-    fn get_cached_size(&self) -> u32 {
-        self.cached_size.get()
-    }
-
-    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
-        &self.unknown_fields
-    }
-
-    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
-        &mut self.unknown_fields
-    }
-
-    fn as_any(&self) -> &dyn (::std::any::Any) {
-        self as &dyn (::std::any::Any)
-    }
-    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
-        self as &mut dyn (::std::any::Any)
-    }
-    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
-        self
-    }
-
-    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
-        Self::descriptor_static()
-    }
-
-    fn new() -> DeleteWorkspaceRequest {
-        DeleteWorkspaceRequest::new()
-    }
-
-    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
-        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
-        descriptor.get(|| {
-            let mut fields = ::std::vec::Vec::new();
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "workspace_id",
-                |m: &DeleteWorkspaceRequest| { &m.workspace_id },
-                |m: &mut DeleteWorkspaceRequest| { &mut m.workspace_id },
-            ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteWorkspaceRequest>(
-                "DeleteWorkspaceRequest",
-                fields,
-                file_descriptor_proto()
-            )
-        })
-    }
-
-    fn default_instance() -> &'static DeleteWorkspaceRequest {
-        static instance: ::protobuf::rt::LazyV2<DeleteWorkspaceRequest> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(DeleteWorkspaceRequest::new)
-    }
-}
-
-impl ::protobuf::Clear for DeleteWorkspaceRequest {
-    fn clear(&mut self) {
-        self.workspace_id.clear();
-        self.unknown_fields.clear();
-    }
-}
-
-impl ::std::fmt::Debug for DeleteWorkspaceRequest {
-    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
-        ::protobuf::text_format::fmt(self, f)
-    }
-}
-
-impl ::protobuf::reflect::ProtobufValue for DeleteWorkspaceRequest {
-    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
-        ::protobuf::reflect::ReflectValueRef::Message(self)
-    }
-}
-
-#[derive(PartialEq,Clone,Default)]
-pub struct DeleteWorkspaceParams {
-    // message fields
-    pub workspace_id: ::std::string::String,
-    // special fields
-    pub unknown_fields: ::protobuf::UnknownFields,
-    pub cached_size: ::protobuf::CachedSize,
-}
-
-impl<'a> ::std::default::Default for &'a DeleteWorkspaceParams {
-    fn default() -> &'a DeleteWorkspaceParams {
-        <DeleteWorkspaceParams as ::protobuf::Message>::default_instance()
-    }
-}
-
-impl DeleteWorkspaceParams {
-    pub fn new() -> DeleteWorkspaceParams {
-        ::std::default::Default::default()
-    }
-
-    // string workspace_id = 1;
-
-
-    pub fn get_workspace_id(&self) -> &str {
-        &self.workspace_id
-    }
-    pub fn clear_workspace_id(&mut self) {
-        self.workspace_id.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_workspace_id(&mut self, v: ::std::string::String) {
-        self.workspace_id = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_workspace_id(&mut self) -> &mut ::std::string::String {
-        &mut self.workspace_id
-    }
-
-    // Take field
-    pub fn take_workspace_id(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.workspace_id, ::std::string::String::new())
-    }
-}
-
-impl ::protobuf::Message for DeleteWorkspaceParams {
-    fn is_initialized(&self) -> bool {
-        true
-    }
-
-    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        while !is.eof()? {
-            let (field_number, wire_type) = is.read_tag_unpack()?;
-            match field_number {
-                1 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.workspace_id)?;
-                },
-                _ => {
-                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
-                },
-            };
-        }
-        ::std::result::Result::Ok(())
-    }
-
-    // Compute sizes of nested messages
-    #[allow(unused_variables)]
-    fn compute_size(&self) -> u32 {
-        let mut my_size = 0;
-        if !self.workspace_id.is_empty() {
-            my_size += ::protobuf::rt::string_size(1, &self.workspace_id);
-        }
-        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
-        self.cached_size.set(my_size);
-        my_size
-    }
-
-    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if !self.workspace_id.is_empty() {
-            os.write_string(1, &self.workspace_id)?;
-        }
-        os.write_unknown_fields(self.get_unknown_fields())?;
-        ::std::result::Result::Ok(())
-    }
-
-    fn get_cached_size(&self) -> u32 {
-        self.cached_size.get()
-    }
-
-    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
-        &self.unknown_fields
-    }
-
-    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
-        &mut self.unknown_fields
-    }
-
-    fn as_any(&self) -> &dyn (::std::any::Any) {
-        self as &dyn (::std::any::Any)
-    }
-    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
-        self as &mut dyn (::std::any::Any)
-    }
-    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
-        self
-    }
-
-    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
-        Self::descriptor_static()
-    }
-
-    fn new() -> DeleteWorkspaceParams {
-        DeleteWorkspaceParams::new()
-    }
-
-    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
-        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
-        descriptor.get(|| {
-            let mut fields = ::std::vec::Vec::new();
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "workspace_id",
-                |m: &DeleteWorkspaceParams| { &m.workspace_id },
-                |m: &mut DeleteWorkspaceParams| { &mut m.workspace_id },
-            ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteWorkspaceParams>(
-                "DeleteWorkspaceParams",
-                fields,
-                file_descriptor_proto()
-            )
-        })
-    }
-
-    fn default_instance() -> &'static DeleteWorkspaceParams {
-        static instance: ::protobuf::rt::LazyV2<DeleteWorkspaceParams> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(DeleteWorkspaceParams::new)
-    }
-}
-
-impl ::protobuf::Clear for DeleteWorkspaceParams {
-    fn clear(&mut self) {
-        self.workspace_id.clear();
-        self.unknown_fields.clear();
-    }
-}
-
-impl ::std::fmt::Debug for DeleteWorkspaceParams {
-    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
-        ::protobuf::text_format::fmt(self, f)
-    }
-}
-
-impl ::protobuf::reflect::ProtobufValue for DeleteWorkspaceParams {
-    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
-        ::protobuf::reflect::ReflectValueRef::Message(self)
-    }
-}
-
-static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x16workspace_delete.proto\";\n\x16DeleteWorkspaceRequest\x12!\n\x0cwo\
-    rkspace_id\x18\x01\x20\x01(\tR\x0bworkspaceId\":\n\x15DeleteWorkspacePar\
-    ams\x12!\n\x0cworkspace_id\x18\x01\x20\x01(\tR\x0bworkspaceIdJ\xb0\x01\n\
-    \x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
-    \x12\x04\x02\0\x04\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x1e\n\x0b\n\
-    \x04\x04\0\x02\0\x12\x03\x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\
-    \x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\
-    \x04\0\x02\0\x03\x12\x03\x03\x1a\x1b\n\n\n\x02\x04\x01\x12\x04\x05\0\x07\
-    \x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x1d\n\x0b\n\x04\x04\x01\x02\0\
-    \x12\x03\x06\x04\x1c\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x06\x04\n\n\
-    \x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\x0b\x17\n\x0c\n\x05\x04\x01\x02\
-    \0\x03\x12\x03\x06\x1a\x1bb\x06proto3\
-";
-
-static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
-
-fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
-    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
-}
-
-pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
-    file_descriptor_proto_lazy.get(|| {
-        parse_descriptor_proto()
-    })
-}

+ 317 - 0
rust-lib/flowy-workspace-infra/src/protobuf/model/workspace_setting.rs

@@ -0,0 +1,317 @@
+// This file is generated by rust-protobuf 2.22.1. Do not edit
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(box_pointers)]
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_imports)]
+#![allow(unused_results)]
+//! Generated file from `workspace_setting.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
+
+#[derive(PartialEq,Clone,Default)]
+pub struct CurrentWorkspaceSetting {
+    // message fields
+    pub workspace: ::protobuf::SingularPtrField<super::workspace_create::Workspace>,
+    // message oneof groups
+    pub one_of_latest_view: ::std::option::Option<CurrentWorkspaceSetting_oneof_one_of_latest_view>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a CurrentWorkspaceSetting {
+    fn default() -> &'a CurrentWorkspaceSetting {
+        <CurrentWorkspaceSetting as ::protobuf::Message>::default_instance()
+    }
+}
+
+#[derive(Clone,PartialEq,Debug)]
+pub enum CurrentWorkspaceSetting_oneof_one_of_latest_view {
+    latest_view(super::view_create::View),
+}
+
+impl CurrentWorkspaceSetting {
+    pub fn new() -> CurrentWorkspaceSetting {
+        ::std::default::Default::default()
+    }
+
+    // .Workspace workspace = 1;
+
+
+    pub fn get_workspace(&self) -> &super::workspace_create::Workspace {
+        self.workspace.as_ref().unwrap_or_else(|| <super::workspace_create::Workspace as ::protobuf::Message>::default_instance())
+    }
+    pub fn clear_workspace(&mut self) {
+        self.workspace.clear();
+    }
+
+    pub fn has_workspace(&self) -> bool {
+        self.workspace.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_workspace(&mut self, v: super::workspace_create::Workspace) {
+        self.workspace = ::protobuf::SingularPtrField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_workspace(&mut self) -> &mut super::workspace_create::Workspace {
+        if self.workspace.is_none() {
+            self.workspace.set_default();
+        }
+        self.workspace.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_workspace(&mut self) -> super::workspace_create::Workspace {
+        self.workspace.take().unwrap_or_else(|| super::workspace_create::Workspace::new())
+    }
+
+    // .View latest_view = 2;
+
+
+    pub fn get_latest_view(&self) -> &super::view_create::View {
+        match self.one_of_latest_view {
+            ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(ref v)) => v,
+            _ => <super::view_create::View as ::protobuf::Message>::default_instance(),
+        }
+    }
+    pub fn clear_latest_view(&mut self) {
+        self.one_of_latest_view = ::std::option::Option::None;
+    }
+
+    pub fn has_latest_view(&self) -> bool {
+        match self.one_of_latest_view {
+            ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(..)) => true,
+            _ => false,
+        }
+    }
+
+    // Param is passed by value, moved
+    pub fn set_latest_view(&mut self, v: super::view_create::View) {
+        self.one_of_latest_view = ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(v))
+    }
+
+    // Mutable pointer to the field.
+    pub fn mut_latest_view(&mut self) -> &mut super::view_create::View {
+        if let ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(_)) = self.one_of_latest_view {
+        } else {
+            self.one_of_latest_view = ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(super::view_create::View::new()));
+        }
+        match self.one_of_latest_view {
+            ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(ref mut v)) => v,
+            _ => panic!(),
+        }
+    }
+
+    // Take field
+    pub fn take_latest_view(&mut self) -> super::view_create::View {
+        if self.has_latest_view() {
+            match self.one_of_latest_view.take() {
+                ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(v)) => v,
+                _ => panic!(),
+            }
+        } else {
+            super::view_create::View::new()
+        }
+    }
+}
+
+impl ::protobuf::Message for CurrentWorkspaceSetting {
+    fn is_initialized(&self) -> bool {
+        for v in &self.workspace {
+            if !v.is_initialized() {
+                return false;
+            }
+        };
+        if let Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(ref v)) = self.one_of_latest_view {
+            if !v.is_initialized() {
+                return false;
+            }
+        }
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.workspace)?;
+                },
+                2 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    self.one_of_latest_view = ::std::option::Option::Some(CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(is.read_message()?));
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if let Some(ref v) = self.workspace.as_ref() {
+            let len = v.compute_size();
+            my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
+        }
+        if let ::std::option::Option::Some(ref v) = self.one_of_latest_view {
+            match v {
+                &CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(ref v) => {
+                    let len = v.compute_size();
+                    my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
+                },
+            };
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if let Some(ref v) = self.workspace.as_ref() {
+            os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?;
+            os.write_raw_varint32(v.get_cached_size())?;
+            v.write_to_with_cached_sizes(os)?;
+        }
+        if let ::std::option::Option::Some(ref v) = self.one_of_latest_view {
+            match v {
+                &CurrentWorkspaceSetting_oneof_one_of_latest_view::latest_view(ref v) => {
+                    os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?;
+                    os.write_raw_varint32(v.get_cached_size())?;
+                    v.write_to_with_cached_sizes(os)?;
+                },
+            };
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> CurrentWorkspaceSetting {
+        CurrentWorkspaceSetting::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<super::workspace_create::Workspace>>(
+                "workspace",
+                |m: &CurrentWorkspaceSetting| { &m.workspace },
+                |m: &mut CurrentWorkspaceSetting| { &mut m.workspace },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, super::view_create::View>(
+                "latest_view",
+                CurrentWorkspaceSetting::has_latest_view,
+                CurrentWorkspaceSetting::get_latest_view,
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<CurrentWorkspaceSetting>(
+                "CurrentWorkspaceSetting",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static CurrentWorkspaceSetting {
+        static instance: ::protobuf::rt::LazyV2<CurrentWorkspaceSetting> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(CurrentWorkspaceSetting::new)
+    }
+}
+
+impl ::protobuf::Clear for CurrentWorkspaceSetting {
+    fn clear(&mut self) {
+        self.workspace.clear();
+        self.one_of_latest_view = ::std::option::Option::None;
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for CurrentWorkspaceSetting {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for CurrentWorkspaceSetting {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x17workspace_setting.proto\x1a\x11view_create.proto\x1a\x16workspace_\
+    create.proto\"\x83\x01\n\x17CurrentWorkspaceSetting\x12(\n\tworkspace\
+    \x18\x01\x20\x01(\x0b2\n.WorkspaceR\tworkspace\x12(\n\x0blatest_view\x18\
+    \x02\x20\x01(\x0b2\x05.ViewH\0R\nlatestViewB\x14\n\x12one_of_latest_view\
+    J\xc9\x01\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\
+    \n\x02\x03\0\x12\x03\x01\0\x1b\n\t\n\x02\x03\x01\x12\x03\x02\0\x20\n\n\n\
+    \x02\x04\0\x12\x04\x04\0\x07\x01\n\n\n\x03\x04\0\x01\x12\x03\x04\x08\x1f\
+    \n\x0b\n\x04\x04\0\x02\0\x12\x03\x05\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x06\
+    \x12\x03\x05\x04\r\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x05\x0e\x17\n\x0c\
+    \n\x05\x04\0\x02\0\x03\x12\x03\x05\x1a\x1b\n\x0b\n\x04\x04\0\x08\0\x12\
+    \x03\x06\x046\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x06\n\x1c\n\x0b\n\x04\
+    \x04\0\x02\x01\x12\x03\x06\x1f4\n\x0c\n\x05\x04\0\x02\x01\x06\x12\x03\
+    \x06\x1f#\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x06$/\n\x0c\n\x05\x04\0\
+    \x02\x01\x03\x12\x03\x0623b\x06proto3\
+";
+
+static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
+
+fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
+    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+}
+
+pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+    file_descriptor_proto_lazy.get(|| {
+        parse_descriptor_proto()
+    })
+}

+ 0 - 205
rust-lib/flowy-workspace-infra/src/protobuf/model/workspace_user_detail.rs

@@ -1,205 +0,0 @@
-// This file is generated by rust-protobuf 2.22.1. Do not edit
-// @generated
-
-// https://github.com/rust-lang/rust-clippy/issues/702
-#![allow(unknown_lints)]
-#![allow(clippy::all)]
-
-#![allow(unused_attributes)]
-#![cfg_attr(rustfmt, rustfmt::skip)]
-
-#![allow(box_pointers)]
-#![allow(dead_code)]
-#![allow(missing_docs)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-#![allow(non_upper_case_globals)]
-#![allow(trivial_casts)]
-#![allow(unused_imports)]
-#![allow(unused_results)]
-//! Generated file from `workspace_user_detail.proto`
-
-/// Generated files are compatible only with the same version
-/// of protobuf runtime.
-// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
-
-#[derive(PartialEq,Clone,Default)]
-pub struct CurrentWorkspace {
-    // message fields
-    pub workspace_id: ::std::string::String,
-    // special fields
-    pub unknown_fields: ::protobuf::UnknownFields,
-    pub cached_size: ::protobuf::CachedSize,
-}
-
-impl<'a> ::std::default::Default for &'a CurrentWorkspace {
-    fn default() -> &'a CurrentWorkspace {
-        <CurrentWorkspace as ::protobuf::Message>::default_instance()
-    }
-}
-
-impl CurrentWorkspace {
-    pub fn new() -> CurrentWorkspace {
-        ::std::default::Default::default()
-    }
-
-    // string workspace_id = 1;
-
-
-    pub fn get_workspace_id(&self) -> &str {
-        &self.workspace_id
-    }
-    pub fn clear_workspace_id(&mut self) {
-        self.workspace_id.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_workspace_id(&mut self, v: ::std::string::String) {
-        self.workspace_id = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_workspace_id(&mut self) -> &mut ::std::string::String {
-        &mut self.workspace_id
-    }
-
-    // Take field
-    pub fn take_workspace_id(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.workspace_id, ::std::string::String::new())
-    }
-}
-
-impl ::protobuf::Message for CurrentWorkspace {
-    fn is_initialized(&self) -> bool {
-        true
-    }
-
-    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        while !is.eof()? {
-            let (field_number, wire_type) = is.read_tag_unpack()?;
-            match field_number {
-                1 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.workspace_id)?;
-                },
-                _ => {
-                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
-                },
-            };
-        }
-        ::std::result::Result::Ok(())
-    }
-
-    // Compute sizes of nested messages
-    #[allow(unused_variables)]
-    fn compute_size(&self) -> u32 {
-        let mut my_size = 0;
-        if !self.workspace_id.is_empty() {
-            my_size += ::protobuf::rt::string_size(1, &self.workspace_id);
-        }
-        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
-        self.cached_size.set(my_size);
-        my_size
-    }
-
-    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if !self.workspace_id.is_empty() {
-            os.write_string(1, &self.workspace_id)?;
-        }
-        os.write_unknown_fields(self.get_unknown_fields())?;
-        ::std::result::Result::Ok(())
-    }
-
-    fn get_cached_size(&self) -> u32 {
-        self.cached_size.get()
-    }
-
-    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
-        &self.unknown_fields
-    }
-
-    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
-        &mut self.unknown_fields
-    }
-
-    fn as_any(&self) -> &dyn (::std::any::Any) {
-        self as &dyn (::std::any::Any)
-    }
-    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
-        self as &mut dyn (::std::any::Any)
-    }
-    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
-        self
-    }
-
-    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
-        Self::descriptor_static()
-    }
-
-    fn new() -> CurrentWorkspace {
-        CurrentWorkspace::new()
-    }
-
-    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
-        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
-        descriptor.get(|| {
-            let mut fields = ::std::vec::Vec::new();
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "workspace_id",
-                |m: &CurrentWorkspace| { &m.workspace_id },
-                |m: &mut CurrentWorkspace| { &mut m.workspace_id },
-            ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<CurrentWorkspace>(
-                "CurrentWorkspace",
-                fields,
-                file_descriptor_proto()
-            )
-        })
-    }
-
-    fn default_instance() -> &'static CurrentWorkspace {
-        static instance: ::protobuf::rt::LazyV2<CurrentWorkspace> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(CurrentWorkspace::new)
-    }
-}
-
-impl ::protobuf::Clear for CurrentWorkspace {
-    fn clear(&mut self) {
-        self.workspace_id.clear();
-        self.unknown_fields.clear();
-    }
-}
-
-impl ::std::fmt::Debug for CurrentWorkspace {
-    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
-        ::protobuf::text_format::fmt(self, f)
-    }
-}
-
-impl ::protobuf::reflect::ProtobufValue for CurrentWorkspace {
-    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
-        ::protobuf::reflect::ReflectValueRef::Message(self)
-    }
-}
-
-static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x1bworkspace_user_detail.proto\"5\n\x10CurrentWorkspace\x12!\n\x0cwor\
-    kspace_id\x18\x01\x20\x01(\tR\x0bworkspaceIdJa\n\x06\x12\x04\0\0\x04\x01\
-    \n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\
-    \n\n\x03\x04\0\x01\x12\x03\x02\x08\x18\n\x0b\n\x04\x04\0\x02\0\x12\x03\
-    \x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\
-    \x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\
-    \x03\x1a\x1bb\x06proto3\
-";
-
-static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
-
-fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
-    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
-}
-
-pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
-    file_descriptor_proto_lazy.get(|| {
-        parse_descriptor_proto()
-    })
-}

+ 0 - 8
rust-lib/flowy-workspace-infra/src/protobuf/proto/workspace_delete.proto

@@ -1,8 +0,0 @@
-syntax = "proto3";
-
-message DeleteWorkspaceRequest {
-    string workspace_id = 1;
-}
-message DeleteWorkspaceParams {
-    string workspace_id = 1;
-}

+ 8 - 0
rust-lib/flowy-workspace-infra/src/protobuf/proto/workspace_setting.proto

@@ -0,0 +1,8 @@
+syntax = "proto3";
+import "view_create.proto";
+import "workspace_create.proto";
+
+message CurrentWorkspaceSetting {
+    Workspace workspace = 1;
+    oneof one_of_latest_view { View latest_view = 2; };
+}

+ 0 - 5
rust-lib/flowy-workspace-infra/src/protobuf/proto/workspace_user_detail.proto

@@ -1,5 +0,0 @@
-syntax = "proto3";
-
-message CurrentWorkspace {
-    string workspace_id = 1;
-}

+ 1 - 1
rust-lib/flowy-workspace/Flowy.toml

@@ -1,3 +1,3 @@
 
-proto_crates = ["src/entities", "src/event.rs", "src/errors.rs", "src/services/notify"]
+proto_crates = ["src/entities", "src/event.rs", "src/errors.rs", "src/notify"]
 event_files = ["src/event.rs"]

+ 2 - 2
rust-lib/flowy-workspace/src/event.rs

@@ -7,13 +7,13 @@ pub enum WorkspaceEvent {
     #[event(input = "CreateWorkspaceRequest", output = "Workspace")]
     CreateWorkspace   = 0,
 
-    #[event(output = "Workspace")]
+    #[event(output = "CurrentWorkspaceSetting")]
     ReadCurWorkspace  = 1,
 
     #[event(input = "QueryWorkspaceRequest", output = "RepeatedWorkspace")]
     ReadWorkspaces    = 2,
 
-    #[event(input = "DeleteWorkspaceRequest")]
+    #[event(input = "QueryWorkspaceRequest")]
     DeleteWorkspace   = 3,
 
     #[event(input = "QueryWorkspaceRequest", output = "Workspace")]

+ 1 - 1
rust-lib/flowy-workspace/src/handlers/workspace_handler.rs

@@ -18,7 +18,7 @@ pub(crate) async fn create_workspace_handler(
 #[tracing::instrument(skip(controller), err)]
 pub(crate) async fn read_cur_workspace_handler(
     controller: Unit<Arc<WorkspaceController>>,
-) -> DataResult<Workspace, WorkspaceError> {
+) -> DataResult<CurrentWorkspaceSetting, WorkspaceError> {
     let workspace = controller.read_current_workspace().await?;
     data_result(workspace)
 }

+ 2 - 9
rust-lib/flowy-workspace/src/services/server/mod.rs

@@ -10,14 +10,7 @@ use crate::{
         app::{App, AppIdentifier, CreateAppParams, UpdateAppParams},
         trash::{RepeatedTrash, TrashIdentifiers},
         view::{CreateViewParams, UpdateViewParams, View, ViewIdentifier, ViewIdentifiers},
-        workspace::{
-            CreateWorkspaceParams,
-            DeleteWorkspaceParams,
-            RepeatedWorkspace,
-            UpdateWorkspaceParams,
-            Workspace,
-            WorkspaceIdentifier,
-        },
+        workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceIdentifier},
     },
     errors::WorkspaceError,
 };
@@ -41,7 +34,7 @@ pub trait WorkspaceServerAPI {
 
     fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> ResultFuture<(), WorkspaceError>;
 
-    fn delete_workspace(&self, token: &str, params: DeleteWorkspaceParams) -> ResultFuture<(), WorkspaceError>;
+    fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> ResultFuture<(), WorkspaceError>;
 
     // View
     fn create_view(&self, token: &str, params: CreateViewParams) -> ResultFuture<View, WorkspaceError>;

+ 2 - 9
rust-lib/flowy-workspace/src/services/server/server_api.rs

@@ -3,14 +3,7 @@ use crate::{
         app::{App, AppIdentifier, CreateAppParams, UpdateAppParams},
         trash::{RepeatedTrash, TrashIdentifiers},
         view::{CreateViewParams, UpdateViewParams, View, ViewIdentifier, ViewIdentifiers},
-        workspace::{
-            CreateWorkspaceParams,
-            DeleteWorkspaceParams,
-            RepeatedWorkspace,
-            UpdateWorkspaceParams,
-            Workspace,
-            WorkspaceIdentifier,
-        },
+        workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceIdentifier},
     },
     errors::WorkspaceError,
     notify::{send_dart_notification, WorkspaceNotification},
@@ -78,7 +71,7 @@ impl WorkspaceServerAPI for WorkspaceServer {
         })
     }
 
-    fn delete_workspace(&self, token: &str, params: DeleteWorkspaceParams) -> ResultFuture<(), WorkspaceError> {
+    fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> ResultFuture<(), WorkspaceError> {
         let token = token.to_owned();
         let url = self.config.workspace_url();
         ResultFuture::new(async move {

+ 2 - 9
rust-lib/flowy-workspace/src/services/server/server_api_mock.rs

@@ -3,14 +3,7 @@ use crate::{
         app::{App, AppIdentifier, CreateAppParams, RepeatedApp, UpdateAppParams},
         trash::{RepeatedTrash, TrashIdentifiers},
         view::{CreateViewParams, RepeatedView, UpdateViewParams, View, ViewIdentifier, ViewIdentifiers},
-        workspace::{
-            CreateWorkspaceParams,
-            DeleteWorkspaceParams,
-            RepeatedWorkspace,
-            UpdateWorkspaceParams,
-            Workspace,
-            WorkspaceIdentifier,
-        },
+        workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceIdentifier},
     },
     errors::WorkspaceError,
     services::server::WorkspaceServerAPI,
@@ -51,7 +44,7 @@ impl WorkspaceServerAPI for WorkspaceServerMock {
         ResultFuture::new(async { Ok(()) })
     }
 
-    fn delete_workspace(&self, _token: &str, _params: DeleteWorkspaceParams) -> ResultFuture<(), WorkspaceError> {
+    fn delete_workspace(&self, _token: &str, _params: WorkspaceIdentifier) -> ResultFuture<(), WorkspaceError> {
         ResultFuture::new(async { Ok(()) })
     }
 

+ 19 - 0
rust-lib/flowy-workspace/src/services/view_controller.rs

@@ -19,8 +19,11 @@ use crate::{
     services::{server::Server, TrashCan, TrashEvent},
     sql_tables::view::{ViewTable, ViewTableChangeset, ViewTableSql},
 };
+use flowy_infra::kv::KV;
 use flowy_workspace_infra::entities::share::{ExportData, ExportParams};
 
+const LATEST_VIEW_ID: &str = "latest_view_id";
+
 pub(crate) struct ViewController {
     user: Arc<dyn WorkspaceUser>,
     server: Server,
@@ -108,7 +111,10 @@ impl ViewController {
 
     #[tracing::instrument(level = "debug", skip(self, params), fields(doc_id = %params.doc_id), err)]
     pub(crate) async fn open_view(&self, params: DocIdentifier) -> Result<DocDelta, WorkspaceError> {
+        let doc_id = params.doc_id.clone();
         let edit_context = self.document.open(params, self.database.db_pool()?).await?;
+
+        KV::set_str(LATEST_VIEW_ID, doc_id);
         Ok(edit_context.delta().await.map_err(internal_error)?)
     }
 
@@ -188,6 +194,19 @@ impl ViewController {
         let doc = self.document.apply_doc_delta(params).await?;
         Ok(doc)
     }
+
+    pub(crate) fn latest_visit_view(&self) -> WorkspaceResult<Option<View>> {
+        match KV::get_str(LATEST_VIEW_ID) {
+            None => Ok(None),
+            Some(view_id) => {
+                let conn = self.database.db_connection()?;
+                let view_table = ViewTableSql::read_view(&view_id, &*conn)?;
+                Ok(Some(view_table.into()))
+            },
+        }
+    }
+
+    pub(crate) fn set_latest_view(&self, view: &View) { KV::set_str(LATEST_VIEW_ID, view.id.clone()); }
 }
 
 impl ViewController {

+ 21 - 13
rust-lib/flowy-workspace/src/services/workspace_controller.rs

@@ -9,7 +9,7 @@ use chrono::Utc;
 use flowy_database::SqliteConnection;
 use flowy_infra::kv::KV;
 use flowy_workspace_infra::{
-    entities::{app::RepeatedApp, workspace::*},
+    entities::{app::RepeatedApp, view::View, workspace::*},
     user_default,
 };
 use lazy_static::lazy_static;
@@ -51,14 +51,13 @@ impl WorkspaceController {
         }
     }
 
-    fn init(&self, token: &str) -> Result<(), WorkspaceError> {
+    async fn init(&self, token: &str) -> Result<(), WorkspaceError> {
         if let Some(is_init) = INIT_WORKSPACE.read().get(token) {
             if *is_init {
                 return Ok(());
             }
         }
         INIT_WORKSPACE.write().insert(token.to_owned(), true);
-
         let _ = self.server.init();
         let _ = self.trash_can.init()?;
         let _ = self.view_controller.init()?;
@@ -67,19 +66,19 @@ impl WorkspaceController {
         Ok(())
     }
 
-    pub fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> {
+    pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> {
         // TODO: (nathan) do something here
 
         log::debug!("workspace initialize after sign in");
-        let _ = self.init(token)?;
+        let _ = self.init(token).await?;
         Ok(())
     }
 
-    pub fn user_did_logout(&self) {
+    pub async fn user_did_logout(&self) {
         // TODO: (nathan) do something here
     }
 
-    pub fn user_session_expired(&self) {
+    pub async fn user_session_expired(&self) {
         // TODO: (nathan) do something here
     }
 
@@ -94,7 +93,10 @@ impl WorkspaceController {
         for mut app in apps {
             let views = app.take_belongings().into_inner();
             let _ = self.app_controller.create_app(app).await?;
-            for view in views {
+            for (index, view) in views.into_iter().enumerate() {
+                if index == 0 {
+                    self.view_controller.set_latest_view(&view);
+                }
                 let _ = self.view_controller.create_view(view).await?;
             }
         }
@@ -109,7 +111,7 @@ impl WorkspaceController {
             .send();
 
         log::debug!("workspace initialize after sign up");
-        let _ = self.init(&token)?;
+        let _ = self.init(&token).await?;
         Ok(())
     }
 
@@ -215,7 +217,7 @@ impl WorkspaceController {
         Ok(workspaces)
     }
 
-    pub(crate) async fn read_current_workspace(&self) -> Result<Workspace, WorkspaceError> {
+    pub(crate) async fn read_current_workspace(&self) -> Result<CurrentWorkspaceSetting, WorkspaceError> {
         let workspace_id = get_current_workspace()?;
         let user_id = self.user.user_id()?;
         let params = WorkspaceIdentifier {
@@ -223,8 +225,14 @@ impl WorkspaceController {
         };
         let workspace = self.read_local_workspace(workspace_id, &user_id, &*self.database.db_connection()?)?;
 
+        let mut latest_view: Option<View> = None;
+        match self.view_controller.latest_visit_view() {
+            Ok(view) => latest_view = view,
+            Err(_) => {},
+        }
+        let setting = CurrentWorkspaceSetting { workspace, latest_view };
         let _ = self.read_workspaces_on_server(user_id.clone(), params)?;
-        Ok(workspace)
+        Ok(setting)
     }
 
     pub(crate) async fn read_current_workspace_apps(&self) -> Result<RepeatedApp, WorkspaceError> {
@@ -310,8 +318,8 @@ impl WorkspaceController {
 
     #[tracing::instrument(level = "debug", skip(self), err)]
     fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
-        let params = DeleteWorkspaceParams {
-            workspace_id: workspace_id.to_string(),
+        let params = WorkspaceIdentifier {
+            workspace_id: Some(workspace_id.to_string()),
         };
         let (token, server) = self.token_with_server()?;
         tokio::spawn(async move {