瀏覽代碼

update view & update app & add some rust test

appflowy 3 年之前
父節點
當前提交
c8ba8284ef
共有 73 個文件被更改,包括 1898 次插入227 次删除
  1. 58 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_delete.pb.dart
  2. 7 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_delete.pbenum.dart
  3. 20 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_delete.pbjson.dart
  4. 9 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_delete.pbserver.dart
  5. 14 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_query.pb.dart
  6. 2 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_query.pbjson.dart
  7. 27 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_update.pb.dart
  8. 3 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_update.pbjson.dart
  9. 15 7
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart
  10. 9 5
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart
  11. 3 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart
  12. 58 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_delete.pb.dart
  13. 7 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_delete.pbenum.dart
  14. 20 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_delete.pbjson.dart
  15. 9 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_delete.pbserver.dart
  16. 14 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_query.pb.dart
  17. 2 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_query.pbjson.dart
  18. 27 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_update.pb.dart
  19. 3 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_update.pbjson.dart
  20. 58 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_delete.pb.dart
  21. 7 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_delete.pbenum.dart
  22. 20 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_delete.pbjson.dart
  23. 9 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_delete.pbserver.dart
  24. 4 2
      rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql
  25. 14 1
      rust-lib/flowy-database/src/macros.rs
  26. 2 0
      rust-lib/flowy-database/src/schema.rs
  27. 3 0
      rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
  28. 2 2
      rust-lib/flowy-sdk/Cargo.toml
  29. 1 0
      rust-lib/flowy-test/src/tester.rs
  30. 28 0
      rust-lib/flowy-workspace/src/entities/app/app_delete.rs
  31. 25 0
      rust-lib/flowy-workspace/src/entities/app/app_query.rs
  32. 5 0
      rust-lib/flowy-workspace/src/entities/app/app_update.rs
  33. 2 0
      rust-lib/flowy-workspace/src/entities/app/mod.rs
  34. 2 0
      rust-lib/flowy-workspace/src/entities/view/mod.rs
  35. 28 0
      rust-lib/flowy-workspace/src/entities/view/view_delete.rs
  36. 22 1
      rust-lib/flowy-workspace/src/entities/view/view_query.rs
  37. 5 0
      rust-lib/flowy-workspace/src/entities/view/view_update.rs
  38. 3 0
      rust-lib/flowy-workspace/src/entities/workspace/mod.rs
  39. 32 0
      rust-lib/flowy-workspace/src/entities/workspace/workspace_delete.rs
  40. 23 7
      rust-lib/flowy-workspace/src/event.rs
  41. 40 7
      rust-lib/flowy-workspace/src/handlers/app_handler.rs
  42. 18 1
      rust-lib/flowy-workspace/src/handlers/view_handler.rs
  43. 4 4
      rust-lib/flowy-workspace/src/handlers/workspace_handler.rs
  44. 16 5
      rust-lib/flowy-workspace/src/module.rs
  45. 1 1
      rust-lib/flowy-workspace/src/observable/observable.rs
  46. 205 0
      rust-lib/flowy-workspace/src/protobuf/model/app_delete.rs
  47. 48 9
      rust-lib/flowy-workspace/src/protobuf/model/app_query.rs
  48. 86 24
      rust-lib/flowy-workspace/src/protobuf/model/app_update.rs
  49. 58 37
      rust-lib/flowy-workspace/src/protobuf/model/event.rs
  50. 9 0
      rust-lib/flowy-workspace/src/protobuf/model/mod.rs
  51. 205 0
      rust-lib/flowy-workspace/src/protobuf/model/view_delete.rs
  52. 45 7
      rust-lib/flowy-workspace/src/protobuf/model/view_query.rs
  53. 82 19
      rust-lib/flowy-workspace/src/protobuf/model/view_update.rs
  54. 205 0
      rust-lib/flowy-workspace/src/protobuf/model/workspace_delete.rs
  55. 5 0
      rust-lib/flowy-workspace/src/protobuf/proto/app_delete.proto
  56. 1 0
      rust-lib/flowy-workspace/src/protobuf/proto/app_query.proto
  57. 1 0
      rust-lib/flowy-workspace/src/protobuf/proto/app_update.proto
  58. 8 4
      rust-lib/flowy-workspace/src/protobuf/proto/event.proto
  59. 5 0
      rust-lib/flowy-workspace/src/protobuf/proto/view_delete.proto
  60. 1 0
      rust-lib/flowy-workspace/src/protobuf/proto/view_query.proto
  61. 1 0
      rust-lib/flowy-workspace/src/protobuf/proto/view_update.proto
  62. 5 0
      rust-lib/flowy-workspace/src/protobuf/proto/workspace_delete.proto
  63. 14 16
      rust-lib/flowy-workspace/src/services/app_controller.rs
  64. 21 2
      rust-lib/flowy-workspace/src/services/view_controller.rs
  65. 27 19
      rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs
  66. 4 0
      rust-lib/flowy-workspace/src/sql_tables/app/app_table.rs
  67. 22 2
      rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs
  68. 4 0
      rust-lib/flowy-workspace/src/sql_tables/view/view_table.rs
  69. 4 2
      rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_sql.rs
  70. 51 20
      rust-lib/flowy-workspace/tests/event/app_test.rs
  71. 60 12
      rust-lib/flowy-workspace/tests/event/helper.rs
  72. 35 0
      rust-lib/flowy-workspace/tests/event/view_test.rs
  73. 5 7
      rust-lib/flowy-workspace/tests/event/workspace_test.rs

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

@@ -0,0 +1,58 @@
+///
+//  Generated code. Do not modify.
+//  source: app_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 DeleteAppRequest extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteAppRequest', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'appId')
+    ..hasRequiredFields = false
+  ;
+
+  DeleteAppRequest._() : super();
+  factory DeleteAppRequest({
+    $core.String? appId,
+  }) {
+    final _result = create();
+    if (appId != null) {
+      _result.appId = appId;
+    }
+    return _result;
+  }
+  factory DeleteAppRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory DeleteAppRequest.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')
+  DeleteAppRequest clone() => DeleteAppRequest()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  DeleteAppRequest copyWith(void Function(DeleteAppRequest) updates) => super.copyWith((message) => updates(message as DeleteAppRequest)) as DeleteAppRequest; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static DeleteAppRequest create() => DeleteAppRequest._();
+  DeleteAppRequest createEmptyInstance() => create();
+  static $pb.PbList<DeleteAppRequest> createRepeated() => $pb.PbList<DeleteAppRequest>();
+  @$core.pragma('dart2js:noInline')
+  static DeleteAppRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DeleteAppRequest>(create);
+  static DeleteAppRequest? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get appId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set appId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasAppId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearAppId() => clearField(1);
+}
+

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

@@ -0,0 +1,7 @@
+///
+//  Generated code. Do not modify.
+//  source: app_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
+

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

@@ -0,0 +1,20 @@
+///
+//  Generated code. Do not modify.
+//  source: app_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 deleteAppRequestDescriptor instead')
+const DeleteAppRequest$json = const {
+  '1': 'DeleteAppRequest',
+  '2': const [
+    const {'1': 'app_id', '3': 1, '4': 1, '5': 9, '10': 'appId'},
+  ],
+};
+
+/// Descriptor for `DeleteAppRequest`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List deleteAppRequestDescriptor = $convert.base64Decode('ChBEZWxldGVBcHBSZXF1ZXN0EhUKBmFwcF9pZBgBIAEoCVIFYXBwSWQ=');

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

@@ -0,0 +1,9 @@
+///
+//  Generated code. Do not modify.
+//  source: app_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
+
+export 'app_delete.pb.dart';
+

+ 14 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_query.pb.dart

@@ -13,6 +13,7 @@ class QueryAppRequest extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryAppRequest', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'appId')
     ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'readViews')
+    ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isTrash')
     ..hasRequiredFields = false
   ;
 
@@ -20,6 +21,7 @@ class QueryAppRequest extends $pb.GeneratedMessage {
   factory QueryAppRequest({
     $core.String? appId,
     $core.bool? readViews,
+    $core.bool? isTrash,
   }) {
     final _result = create();
     if (appId != null) {
@@ -28,6 +30,9 @@ class QueryAppRequest extends $pb.GeneratedMessage {
     if (readViews != null) {
       _result.readViews = readViews;
     }
+    if (isTrash != null) {
+      _result.isTrash = isTrash;
+    }
     return _result;
   }
   factory QueryAppRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -68,5 +73,14 @@ class QueryAppRequest extends $pb.GeneratedMessage {
   $core.bool hasReadViews() => $_has(1);
   @$pb.TagNumber(2)
   void clearReadViews() => clearField(2);
+
+  @$pb.TagNumber(3)
+  $core.bool get isTrash => $_getBF(2);
+  @$pb.TagNumber(3)
+  set isTrash($core.bool v) { $_setBool(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasIsTrash() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearIsTrash() => clearField(3);
 }
 

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

@@ -14,8 +14,9 @@ const QueryAppRequest$json = const {
   '2': const [
     const {'1': 'app_id', '3': 1, '4': 1, '5': 9, '10': 'appId'},
     const {'1': 'read_views', '3': 2, '4': 1, '5': 8, '10': 'readViews'},
+    const {'1': 'is_trash', '3': 3, '4': 1, '5': 8, '10': 'isTrash'},
   ],
 };
 
 /// Descriptor for `QueryAppRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List queryAppRequestDescriptor = $convert.base64Decode('Cg9RdWVyeUFwcFJlcXVlc3QSFQoGYXBwX2lkGAEgASgJUgVhcHBJZBIdCgpyZWFkX3ZpZXdzGAIgASgIUglyZWFkVmlld3M=');
+final $typed_data.Uint8List queryAppRequestDescriptor = $convert.base64Decode('Cg9RdWVyeUFwcFJlcXVlc3QSFQoGYXBwX2lkGAEgASgJUgVhcHBJZBIdCgpyZWFkX3ZpZXdzGAIgASgIUglyZWFkVmlld3MSGQoIaXNfdHJhc2gYAyABKAhSB2lzVHJhc2g=');

+ 27 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_update.pb.dart

@@ -31,6 +31,11 @@ enum UpdateAppRequest_OneOfColorStyle {
   notSet
 }
 
+enum UpdateAppRequest_OneOfIsTrash {
+  isTrash, 
+  notSet
+}
+
 class UpdateAppRequest extends $pb.GeneratedMessage {
   static const $core.Map<$core.int, UpdateAppRequest_OneOfWorkspaceId> _UpdateAppRequest_OneOfWorkspaceIdByTag = {
     2 : UpdateAppRequest_OneOfWorkspaceId.workspaceId,
@@ -48,16 +53,22 @@ class UpdateAppRequest extends $pb.GeneratedMessage {
     5 : UpdateAppRequest_OneOfColorStyle.colorStyle,
     0 : UpdateAppRequest_OneOfColorStyle.notSet
   };
+  static const $core.Map<$core.int, UpdateAppRequest_OneOfIsTrash> _UpdateAppRequest_OneOfIsTrashByTag = {
+    6 : UpdateAppRequest_OneOfIsTrash.isTrash,
+    0 : UpdateAppRequest_OneOfIsTrash.notSet
+  };
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UpdateAppRequest', createEmptyInstance: create)
     ..oo(0, [2])
     ..oo(1, [3])
     ..oo(2, [4])
     ..oo(3, [5])
+    ..oo(4, [6])
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'appId')
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspaceId')
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
     ..aOM<$0.ColorStyle>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'colorStyle', subBuilder: $0.ColorStyle.create)
+    ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isTrash')
     ..hasRequiredFields = false
   ;
 
@@ -68,6 +79,7 @@ class UpdateAppRequest extends $pb.GeneratedMessage {
     $core.String? name,
     $core.String? desc,
     $0.ColorStyle? colorStyle,
+    $core.bool? isTrash,
   }) {
     final _result = create();
     if (appId != null) {
@@ -85,6 +97,9 @@ class UpdateAppRequest extends $pb.GeneratedMessage {
     if (colorStyle != null) {
       _result.colorStyle = colorStyle;
     }
+    if (isTrash != null) {
+      _result.isTrash = isTrash;
+    }
     return _result;
   }
   factory UpdateAppRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -120,6 +135,9 @@ class UpdateAppRequest extends $pb.GeneratedMessage {
   UpdateAppRequest_OneOfColorStyle whichOneOfColorStyle() => _UpdateAppRequest_OneOfColorStyleByTag[$_whichOneof(3)]!;
   void clearOneOfColorStyle() => clearField($_whichOneof(3));
 
+  UpdateAppRequest_OneOfIsTrash whichOneOfIsTrash() => _UpdateAppRequest_OneOfIsTrashByTag[$_whichOneof(4)]!;
+  void clearOneOfIsTrash() => clearField($_whichOneof(4));
+
   @$pb.TagNumber(1)
   $core.String get appId => $_getSZ(0);
   @$pb.TagNumber(1)
@@ -166,5 +184,14 @@ class UpdateAppRequest extends $pb.GeneratedMessage {
   void clearColorStyle() => clearField(5);
   @$pb.TagNumber(5)
   $0.ColorStyle ensureColorStyle() => $_ensure(4);
+
+  @$pb.TagNumber(6)
+  $core.bool get isTrash => $_getBF(5);
+  @$pb.TagNumber(6)
+  set isTrash($core.bool v) { $_setBool(5, v); }
+  @$pb.TagNumber(6)
+  $core.bool hasIsTrash() => $_has(5);
+  @$pb.TagNumber(6)
+  void clearIsTrash() => clearField(6);
 }
 

+ 3 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_update.pbjson.dart

@@ -17,14 +17,16 @@ const UpdateAppRequest$json = const {
     const {'1': 'name', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'name'},
     const {'1': 'desc', '3': 4, '4': 1, '5': 9, '9': 2, '10': 'desc'},
     const {'1': 'color_style', '3': 5, '4': 1, '5': 11, '6': '.ColorStyle', '9': 3, '10': 'colorStyle'},
+    const {'1': 'is_trash', '3': 6, '4': 1, '5': 8, '9': 4, '10': 'isTrash'},
   ],
   '8': const [
     const {'1': 'one_of_workspace_id'},
     const {'1': 'one_of_name'},
     const {'1': 'one_of_desc'},
     const {'1': 'one_of_color_style'},
+    const {'1': 'one_of_is_trash'},
   ],
 };
 
 /// Descriptor for `UpdateAppRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List updateAppRequestDescriptor = $convert.base64Decode('ChBVcGRhdGVBcHBSZXF1ZXN0EhUKBmFwcF9pZBgBIAEoCVIFYXBwSWQSIwoMd29ya3NwYWNlX2lkGAIgASgJSABSC3dvcmtzcGFjZUlkEhQKBG5hbWUYAyABKAlIAVIEbmFtZRIUCgRkZXNjGAQgASgJSAJSBGRlc2MSLgoLY29sb3Jfc3R5bGUYBSABKAsyCy5Db2xvclN0eWxlSANSCmNvbG9yU3R5bGVCFQoTb25lX29mX3dvcmtzcGFjZV9pZEINCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0IUChJvbmVfb2ZfY29sb3Jfc3R5bGU=');
+final $typed_data.Uint8List updateAppRequestDescriptor = $convert.base64Decode('ChBVcGRhdGVBcHBSZXF1ZXN0EhUKBmFwcF9pZBgBIAEoCVIFYXBwSWQSIwoMd29ya3NwYWNlX2lkGAIgASgJSABSC3dvcmtzcGFjZUlkEhQKBG5hbWUYAyABKAlIAVIEbmFtZRIUCgRkZXNjGAQgASgJSAJSBGRlc2MSLgoLY29sb3Jfc3R5bGUYBSABKAsyCy5Db2xvclN0eWxlSANSCmNvbG9yU3R5bGUSGwoIaXNfdHJhc2gYBiABKAhIBFIHaXNUcmFzaEIVChNvbmVfb2Zfd29ya3NwYWNlX2lkQg0KC29uZV9vZl9uYW1lQg0KC29uZV9vZl9kZXNjQhQKEm9uZV9vZl9jb2xvcl9zdHlsZUIRCg9vbmVfb2ZfaXNfdHJhc2g=');

+ 15 - 7
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart

@@ -11,25 +11,33 @@ import 'package:protobuf/protobuf.dart' as $pb;
 
 class WorkspaceEvent extends $pb.ProtobufEnum {
   static const WorkspaceEvent CreateWorkspace = WorkspaceEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateWorkspace');
-  static const WorkspaceEvent GetCurWorkspace = WorkspaceEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCurWorkspace');
-  static const WorkspaceEvent GetWorkspace = WorkspaceEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetWorkspace');
-  static const WorkspaceEvent ReadAllWorkspace = WorkspaceEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadAllWorkspace');
+  static const WorkspaceEvent ReadCurWorkspace = WorkspaceEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadCurWorkspace');
+  static const WorkspaceEvent ReadWorkspace = WorkspaceEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadWorkspace');
+  static const WorkspaceEvent DeleteWorkspace = WorkspaceEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteWorkspace');
+  static const WorkspaceEvent ReadAllWorkspace = WorkspaceEvent._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadAllWorkspace');
   static const WorkspaceEvent CreateApp = WorkspaceEvent._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateApp');
-  static const WorkspaceEvent GetApp = WorkspaceEvent._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetApp');
+  static const WorkspaceEvent DeleteApp = WorkspaceEvent._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteApp');
+  static const WorkspaceEvent ReadApp = WorkspaceEvent._(103, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadApp');
+  static const WorkspaceEvent UpdateApp = WorkspaceEvent._(104, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateApp');
   static const WorkspaceEvent CreateView = WorkspaceEvent._(201, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateView');
   static const WorkspaceEvent ReadView = WorkspaceEvent._(202, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadView');
   static const WorkspaceEvent UpdateView = WorkspaceEvent._(203, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateView');
+  static const WorkspaceEvent DeleteView = WorkspaceEvent._(204, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteView');
 
   static const $core.List<WorkspaceEvent> values = <WorkspaceEvent> [
     CreateWorkspace,
-    GetCurWorkspace,
-    GetWorkspace,
+    ReadCurWorkspace,
+    ReadWorkspace,
+    DeleteWorkspace,
     ReadAllWorkspace,
     CreateApp,
-    GetApp,
+    DeleteApp,
+    ReadApp,
+    UpdateApp,
     CreateView,
     ReadView,
     UpdateView,
+    DeleteView,
   ];
 
   static final $core.Map<$core.int, WorkspaceEvent> _byValue = $pb.ProtobufEnum.initByValue(values);

+ 9 - 5
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart

@@ -13,16 +13,20 @@ const WorkspaceEvent$json = const {
   '1': 'WorkspaceEvent',
   '2': const [
     const {'1': 'CreateWorkspace', '2': 0},
-    const {'1': 'GetCurWorkspace', '2': 1},
-    const {'1': 'GetWorkspace', '2': 2},
-    const {'1': 'ReadAllWorkspace', '2': 3},
+    const {'1': 'ReadCurWorkspace', '2': 1},
+    const {'1': 'ReadWorkspace', '2': 2},
+    const {'1': 'DeleteWorkspace', '2': 3},
+    const {'1': 'ReadAllWorkspace', '2': 4},
     const {'1': 'CreateApp', '2': 101},
-    const {'1': 'GetApp', '2': 102},
+    const {'1': 'DeleteApp', '2': 102},
+    const {'1': 'ReadApp', '2': 103},
+    const {'1': 'UpdateApp', '2': 104},
     const {'1': 'CreateView', '2': 201},
     const {'1': 'ReadView', '2': 202},
     const {'1': 'UpdateView', '2': 203},
+    const {'1': 'DeleteView', '2': 204},
   ],
 };
 
 /// Descriptor for `WorkspaceEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABITCg9HZXRDdXJXb3Jrc3BhY2UQARIQCgxHZXRXb3Jrc3BhY2UQAhIUChBSZWFkQWxsV29ya3NwYWNlEAMSDQoJQ3JlYXRlQXBwEGUSCgoGR2V0QXBwEGYSDwoKQ3JlYXRlVmlldxDJARINCghSZWFkVmlldxDKARIPCgpVcGRhdGVWaWV3EMsB');
+final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABIUChBSZWFkQ3VyV29ya3NwYWNlEAESEQoNUmVhZFdvcmtzcGFjZRACEhMKD0RlbGV0ZVdvcmtzcGFjZRADEhQKEFJlYWRBbGxXb3Jrc3BhY2UQBBINCglDcmVhdGVBcHAQZRINCglEZWxldGVBcHAQZhILCgdSZWFkQXBwEGcSDQoJVXBkYXRlQXBwEGgSDwoKQ3JlYXRlVmlldxDJARINCghSZWFkVmlldxDKARIPCgpVcGRhdGVWaWV3EMsBEg8KCkRlbGV0ZVZpZXcQzAE=');

+ 3 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart

@@ -1,6 +1,8 @@
 // Auto-generated, do not edit 
 export './view_update.pb.dart';
+export './view_delete.pb.dart';
 export './app_query.pb.dart';
+export './workspace_delete.pb.dart';
 export './observable.pb.dart';
 export './errors.pb.dart';
 export './workspace_update.pb.dart';
@@ -12,3 +14,4 @@ export './workspace_user_detail.pb.dart';
 export './workspace_create.pb.dart';
 export './app_update.pb.dart';
 export './view_query.pb.dart';
+export './app_delete.pb.dart';

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

@@ -0,0 +1,58 @@
+///
+//  Generated code. Do not modify.
+//  source: view_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 DeleteViewRequest extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteViewRequest', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
+    ..hasRequiredFields = false
+  ;
+
+  DeleteViewRequest._() : super();
+  factory DeleteViewRequest({
+    $core.String? viewId,
+  }) {
+    final _result = create();
+    if (viewId != null) {
+      _result.viewId = viewId;
+    }
+    return _result;
+  }
+  factory DeleteViewRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory DeleteViewRequest.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')
+  DeleteViewRequest clone() => DeleteViewRequest()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  DeleteViewRequest copyWith(void Function(DeleteViewRequest) updates) => super.copyWith((message) => updates(message as DeleteViewRequest)) as DeleteViewRequest; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static DeleteViewRequest create() => DeleteViewRequest._();
+  DeleteViewRequest createEmptyInstance() => create();
+  static $pb.PbList<DeleteViewRequest> createRepeated() => $pb.PbList<DeleteViewRequest>();
+  @$core.pragma('dart2js:noInline')
+  static DeleteViewRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DeleteViewRequest>(create);
+  static DeleteViewRequest? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get viewId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set viewId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasViewId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearViewId() => clearField(1);
+}
+

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

@@ -0,0 +1,7 @@
+///
+//  Generated code. Do not modify.
+//  source: view_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
+

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

@@ -0,0 +1,20 @@
+///
+//  Generated code. Do not modify.
+//  source: view_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 deleteViewRequestDescriptor instead')
+const DeleteViewRequest$json = const {
+  '1': 'DeleteViewRequest',
+  '2': const [
+    const {'1': 'view_id', '3': 1, '4': 1, '5': 9, '10': 'viewId'},
+  ],
+};
+
+/// Descriptor for `DeleteViewRequest`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List deleteViewRequestDescriptor = $convert.base64Decode('ChFEZWxldGVWaWV3UmVxdWVzdBIXCgd2aWV3X2lkGAEgASgJUgZ2aWV3SWQ=');

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

@@ -0,0 +1,9 @@
+///
+//  Generated code. Do not modify.
+//  source: view_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
+
+export 'view_delete.pb.dart';
+

+ 14 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_query.pb.dart

@@ -12,17 +12,22 @@ import 'package:protobuf/protobuf.dart' as $pb;
 class QueryViewRequest extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryViewRequest', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
+    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isTrash')
     ..hasRequiredFields = false
   ;
 
   QueryViewRequest._() : super();
   factory QueryViewRequest({
     $core.String? viewId,
+    $core.bool? isTrash,
   }) {
     final _result = create();
     if (viewId != null) {
       _result.viewId = viewId;
     }
+    if (isTrash != null) {
+      _result.isTrash = isTrash;
+    }
     return _result;
   }
   factory QueryViewRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -54,5 +59,14 @@ class QueryViewRequest extends $pb.GeneratedMessage {
   $core.bool hasViewId() => $_has(0);
   @$pb.TagNumber(1)
   void clearViewId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.bool get isTrash => $_getBF(1);
+  @$pb.TagNumber(2)
+  set isTrash($core.bool v) { $_setBool(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasIsTrash() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearIsTrash() => clearField(2);
 }
 

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

@@ -13,8 +13,9 @@ const QueryViewRequest$json = const {
   '1': 'QueryViewRequest',
   '2': const [
     const {'1': 'view_id', '3': 1, '4': 1, '5': 9, '10': 'viewId'},
+    const {'1': 'is_trash', '3': 2, '4': 1, '5': 8, '10': 'isTrash'},
   ],
 };
 
 /// Descriptor for `QueryViewRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List queryViewRequestDescriptor = $convert.base64Decode('ChBRdWVyeVZpZXdSZXF1ZXN0EhcKB3ZpZXdfaWQYASABKAlSBnZpZXdJZA==');
+final $typed_data.Uint8List queryViewRequestDescriptor = $convert.base64Decode('ChBRdWVyeVZpZXdSZXF1ZXN0EhcKB3ZpZXdfaWQYASABKAlSBnZpZXdJZBIZCghpc190cmFzaBgCIAEoCFIHaXNUcmFzaA==');

+ 27 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_update.pb.dart

@@ -24,6 +24,11 @@ enum UpdateViewRequest_OneOfThumbnail {
   notSet
 }
 
+enum UpdateViewRequest_OneOfIsTrash {
+  isTrash, 
+  notSet
+}
+
 class UpdateViewRequest extends $pb.GeneratedMessage {
   static const $core.Map<$core.int, UpdateViewRequest_OneOfName> _UpdateViewRequest_OneOfNameByTag = {
     2 : UpdateViewRequest_OneOfName.name,
@@ -37,14 +42,20 @@ class UpdateViewRequest extends $pb.GeneratedMessage {
     4 : UpdateViewRequest_OneOfThumbnail.thumbnail,
     0 : UpdateViewRequest_OneOfThumbnail.notSet
   };
+  static const $core.Map<$core.int, UpdateViewRequest_OneOfIsTrash> _UpdateViewRequest_OneOfIsTrashByTag = {
+    5 : UpdateViewRequest_OneOfIsTrash.isTrash,
+    0 : UpdateViewRequest_OneOfIsTrash.notSet
+  };
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UpdateViewRequest', createEmptyInstance: create)
     ..oo(0, [2])
     ..oo(1, [3])
     ..oo(2, [4])
+    ..oo(3, [5])
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
+    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isTrash')
     ..hasRequiredFields = false
   ;
 
@@ -54,6 +65,7 @@ class UpdateViewRequest extends $pb.GeneratedMessage {
     $core.String? name,
     $core.String? desc,
     $core.String? thumbnail,
+    $core.bool? isTrash,
   }) {
     final _result = create();
     if (viewId != null) {
@@ -68,6 +80,9 @@ class UpdateViewRequest extends $pb.GeneratedMessage {
     if (thumbnail != null) {
       _result.thumbnail = thumbnail;
     }
+    if (isTrash != null) {
+      _result.isTrash = isTrash;
+    }
     return _result;
   }
   factory UpdateViewRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -100,6 +115,9 @@ class UpdateViewRequest extends $pb.GeneratedMessage {
   UpdateViewRequest_OneOfThumbnail whichOneOfThumbnail() => _UpdateViewRequest_OneOfThumbnailByTag[$_whichOneof(2)]!;
   void clearOneOfThumbnail() => clearField($_whichOneof(2));
 
+  UpdateViewRequest_OneOfIsTrash whichOneOfIsTrash() => _UpdateViewRequest_OneOfIsTrashByTag[$_whichOneof(3)]!;
+  void clearOneOfIsTrash() => clearField($_whichOneof(3));
+
   @$pb.TagNumber(1)
   $core.String get viewId => $_getSZ(0);
   @$pb.TagNumber(1)
@@ -135,5 +153,14 @@ class UpdateViewRequest extends $pb.GeneratedMessage {
   $core.bool hasThumbnail() => $_has(3);
   @$pb.TagNumber(4)
   void clearThumbnail() => clearField(4);
+
+  @$pb.TagNumber(5)
+  $core.bool get isTrash => $_getBF(4);
+  @$pb.TagNumber(5)
+  set isTrash($core.bool v) { $_setBool(4, v); }
+  @$pb.TagNumber(5)
+  $core.bool hasIsTrash() => $_has(4);
+  @$pb.TagNumber(5)
+  void clearIsTrash() => clearField(5);
 }
 

+ 3 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_update.pbjson.dart

@@ -16,13 +16,15 @@ const UpdateViewRequest$json = const {
     const {'1': 'name', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'name'},
     const {'1': 'desc', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'desc'},
     const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 2, '10': 'thumbnail'},
+    const {'1': 'is_trash', '3': 5, '4': 1, '5': 8, '9': 3, '10': 'isTrash'},
   ],
   '8': const [
     const {'1': 'one_of_name'},
     const {'1': 'one_of_desc'},
     const {'1': 'one_of_thumbnail'},
+    const {'1': 'one_of_is_trash'},
   ],
 };
 
 /// Descriptor for `UpdateViewRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List updateViewRequestDescriptor = $convert.base64Decode('ChFVcGRhdGVWaWV3UmVxdWVzdBIXCgd2aWV3X2lkGAEgASgJUgZ2aWV3SWQSFAoEbmFtZRgCIAEoCUgAUgRuYW1lEhQKBGRlc2MYAyABKAlIAVIEZGVzYxIeCgl0aHVtYm5haWwYBCABKAlIAlIJdGh1bWJuYWlsQg0KC29uZV9vZl9uYW1lQg0KC29uZV9vZl9kZXNjQhIKEG9uZV9vZl90aHVtYm5haWw=');
+final $typed_data.Uint8List updateViewRequestDescriptor = $convert.base64Decode('ChFVcGRhdGVWaWV3UmVxdWVzdBIXCgd2aWV3X2lkGAEgASgJUgZ2aWV3SWQSFAoEbmFtZRgCIAEoCUgAUgRuYW1lEhQKBGRlc2MYAyABKAlIAVIEZGVzYxIeCgl0aHVtYm5haWwYBCABKAlIAlIJdGh1bWJuYWlsEhsKCGlzX3RyYXNoGAUgASgISANSB2lzVHJhc2hCDQoLb25lX29mX25hbWVCDQoLb25lX29mX2Rlc2NCEgoQb25lX29mX3RodW1ibmFpbEIRCg9vbmVfb2ZfaXNfdHJhc2g=');

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

@@ -0,0 +1,58 @@
+///
+//  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);
+}
+

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

@@ -0,0 +1,7 @@
+///
+//  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
+

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

@@ -0,0 +1,20 @@
+///
+//  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=');

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

@@ -0,0 +1,9 @@
+///
+//  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
+
+export 'workspace_delete.pb.dart';
+

+ 4 - 2
rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql

@@ -26,7 +26,8 @@ CREATE TABLE app_table (
     last_view_id TEXT DEFAULT '',
     modified_time BIGINT NOT NULL DEFAULT 0,
     create_time BIGINT NOT NULL DEFAULT 0,
-    version BIGINT NOT NULL DEFAULT 0
+    version BIGINT NOT NULL DEFAULT 0,
+    is_trash Boolean NOT NULL DEFAULT false
 );
 
 CREATE TABLE view_table (
@@ -38,5 +39,6 @@ CREATE TABLE view_table (
     create_time BIGINT NOT NULL DEFAULT 0,
     thumbnail TEXT NOT NULL DEFAULT '',
     view_type INTEGER NOT NULL DEFAULT 0,
-    version BIGINT NOT NULL DEFAULT 0
+    version BIGINT NOT NULL DEFAULT 0,
+    is_trash Boolean NOT NULL DEFAULT false
 );

+ 14 - 1
rust-lib/flowy-database/src/macros.rs

@@ -10,6 +10,19 @@ macro_rules! diesel_update_table {
         let affected_row = diesel::update(filter)
             .set($changeset)
             .execute(&*$connection)?;
-        // debug_assert_eq!(affected_row, 1);
+        debug_assert_eq!(affected_row, 1);
+    };
+}
+
+#[macro_export]
+macro_rules! diesel_delete_table {
+    (
+        $table_name:ident,
+        $id:ident,
+        $connection:ident
+    ) => {
+        let filter = $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($id));
+        let affected_row = diesel::delete(filter).execute(&*$connection)?;
+        debug_assert_eq!(affected_row, 1);
     };
 }

+ 2 - 0
rust-lib/flowy-database/src/schema.rs

@@ -9,6 +9,7 @@ table! {
         modified_time -> BigInt,
         create_time -> BigInt,
         version -> BigInt,
+        is_trash -> Bool,
     }
 }
 
@@ -45,6 +46,7 @@ table! {
         thumbnail -> Text,
         view_type -> Integer,
         version -> BigInt,
+        is_trash -> Bool,
     }
 }
 

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

@@ -30,13 +30,16 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "App"
         | "RepeatedApp"
         | "UpdateAppRequest"
+        | "DeleteAppRequest"
         | "UpdateWorkspaceRequest"
+        | "DeleteWorkspaceRequest"
         | "CreateWorkspaceRequest"
         | "Workspace"
         | "Workspaces"
         | "QueryWorkspaceRequest"
         | "CurrentWorkspace"
         | "UpdateViewRequest"
+        | "DeleteViewRequest"
         | "QueryViewRequest"
         | "CreateViewRequest"
         | "View"

+ 2 - 2
rust-lib/flowy-sdk/Cargo.toml

@@ -7,8 +7,8 @@ edition = "2018"
 
 [dependencies]
 flowy-dispatch = { path = "../flowy-dispatch", features = ["use_tracing"]}
-#flowy-log = { path = "../flowy-log" }
-flowy-log = { path = "../flowy-log", features = ["use_bunyan"] }
+flowy-log = { path = "../flowy-log" }
+#flowy-log = { path = "../flowy-log", features = ["use_bunyan"] }
 flowy-user = { path = "../flowy-user" }
 flowy-infra = { path = "../flowy-infra" }
 flowy-workspace = { path = "../flowy-workspace" }

+ 1 - 0
rust-lib/flowy-test/src/tester.rs

@@ -77,6 +77,7 @@ pub trait TesterTrait {
         self.mut_context().response = Some(resp);
     }
 
+    // TODO: support return Option<R>
     fn parse<R>(&mut self) -> R
     where
         R: FromBytes,

+ 28 - 0
rust-lib/flowy-workspace/src/entities/app/app_delete.rs

@@ -0,0 +1,28 @@
+use crate::{
+    entities::app::parser::BelongToId,
+    errors::{ErrorBuilder, WorkspaceError, WsErrCode},
+};
+use flowy_derive::ProtoBuf;
+use std::convert::TryInto;
+
+#[derive(Default, ProtoBuf)]
+pub struct DeleteAppRequest {
+    #[pb(index = 1)]
+    pub app_id: String,
+}
+
+pub struct DeleteAppParams {
+    pub app_id: String,
+}
+
+impl TryInto<DeleteAppParams> for DeleteAppRequest {
+    type Error = WorkspaceError;
+
+    fn try_into(self) -> Result<DeleteAppParams, Self::Error> {
+        let app_id = BelongToId::parse(self.app_id)
+            .map_err(|e| ErrorBuilder::new(WsErrCode::AppIdInvalid).msg(e).build())?
+            .0;
+
+        Ok(DeleteAppParams { app_id })
+    }
+}

+ 25 - 0
rust-lib/flowy-workspace/src/entities/app/app_query.rs

@@ -9,11 +9,35 @@ pub struct QueryAppRequest {
 
     #[pb(index = 2)]
     pub read_views: bool,
+
+    #[pb(index = 3)]
+    pub is_trash: bool,
+}
+
+impl QueryAppRequest {
+    pub fn new(app_id: &str) -> Self {
+        QueryAppRequest {
+            app_id: app_id.to_string(),
+            read_views: false,
+            is_trash: false,
+        }
+    }
+
+    pub fn set_read_views(mut self, read_views: bool) -> Self {
+        self.read_views = read_views;
+        self
+    }
+
+    pub fn set_is_trash(mut self, is_trash: bool) -> Self {
+        self.is_trash = is_trash;
+        self
+    }
 }
 
 pub struct QueryAppParams {
     pub app_id: String,
     pub read_views: bool,
+    pub is_trash: bool,
 }
 
 impl TryInto<QueryAppParams> for QueryAppRequest {
@@ -27,6 +51,7 @@ impl TryInto<QueryAppParams> for QueryAppRequest {
         Ok(QueryAppParams {
             app_id,
             read_views: self.read_views,
+            is_trash: self.is_trash,
         })
     }
 }

+ 5 - 0
rust-lib/flowy-workspace/src/entities/app/app_update.rs

@@ -27,6 +27,9 @@ pub struct UpdateAppRequest {
 
     #[pb(index = 5, one_of)]
     pub color_style: Option<ColorStyle>,
+
+    #[pb(index = 6, one_of)]
+    pub is_trash: Option<bool>,
 }
 
 pub struct UpdateAppParams {
@@ -35,6 +38,7 @@ pub struct UpdateAppParams {
     pub name: Option<String>,
     pub desc: Option<String>,
     pub color_style: Option<ColorStyle>,
+    pub is_trash: Option<bool>,
 }
 
 impl TryInto<UpdateAppParams> for UpdateAppRequest {
@@ -90,6 +94,7 @@ impl TryInto<UpdateAppParams> for UpdateAppRequest {
             name,
             desc: self.desc,
             color_style,
+            is_trash: self.is_trash,
         })
     }
 }

+ 2 - 0
rust-lib/flowy-workspace/src/entities/app/mod.rs

@@ -2,8 +2,10 @@ pub use app_create::*;
 pub use app_update::*;
 
 mod app_create;
+mod app_delete;
 mod app_query;
 mod app_update;
 pub mod parser;
 
+pub use app_delete::*;
 pub use app_query::*;

+ 2 - 0
rust-lib/flowy-workspace/src/entities/view/mod.rs

@@ -1,8 +1,10 @@
 mod parser;
 mod view_create;
+mod view_delete;
 mod view_query;
 mod view_update;
 
 pub use view_create::*;
+pub use view_delete::*;
 pub use view_query::*;
 pub use view_update::*;

+ 28 - 0
rust-lib/flowy-workspace/src/entities/view/view_delete.rs

@@ -0,0 +1,28 @@
+use crate::{
+    entities::view::parser::ViewId,
+    errors::{ErrorBuilder, WorkspaceError, WsErrCode},
+};
+use flowy_derive::ProtoBuf;
+use std::convert::TryInto;
+
+#[derive(Default, ProtoBuf)]
+pub struct DeleteViewRequest {
+    #[pb(index = 1)]
+    view_id: String,
+}
+
+pub struct DeleteViewParams {
+    pub(crate) view_id: String,
+}
+
+impl TryInto<DeleteViewParams> for DeleteViewRequest {
+    type Error = WorkspaceError;
+
+    fn try_into(self) -> Result<DeleteViewParams, Self::Error> {
+        let view_id = ViewId::parse(self.view_id)
+            .map_err(|e| ErrorBuilder::new(WsErrCode::ViewIdInvalid).msg(e).build())?
+            .0;
+
+        Ok(DeleteViewParams { view_id })
+    }
+}

+ 22 - 1
rust-lib/flowy-workspace/src/entities/view/view_query.rs

@@ -9,10 +9,28 @@ use std::convert::TryInto;
 pub struct QueryViewRequest {
     #[pb(index = 1)]
     pub view_id: String,
+
+    #[pb(index = 2)]
+    pub is_trash: bool,
+}
+
+impl QueryViewRequest {
+    pub fn new(view_id: &str) -> Self {
+        Self {
+            view_id: view_id.to_owned(),
+            is_trash: false,
+        }
+    }
+
+    pub fn set_is_trash(mut self, is_trash: bool) -> Self {
+        self.is_trash = is_trash;
+        self
+    }
 }
 
 pub struct QueryViewParams {
     pub view_id: String,
+    pub is_trash: bool,
 }
 
 impl TryInto<QueryViewParams> for QueryViewRequest {
@@ -23,6 +41,9 @@ impl TryInto<QueryViewParams> for QueryViewRequest {
             .map_err(|e| ErrorBuilder::new(WsErrCode::ViewIdInvalid).msg(e).build())?
             .0;
 
-        Ok(QueryViewParams { view_id })
+        Ok(QueryViewParams {
+            view_id,
+            is_trash: self.is_trash,
+        })
     }
 }

+ 5 - 0
rust-lib/flowy-workspace/src/entities/view/view_update.rs

@@ -18,6 +18,9 @@ pub struct UpdateViewRequest {
 
     #[pb(index = 4, one_of)]
     pub thumbnail: Option<String>,
+
+    #[pb(index = 5, one_of)]
+    pub is_trash: Option<bool>,
 }
 
 pub struct UpdateViewParams {
@@ -25,6 +28,7 @@ pub struct UpdateViewParams {
     pub name: Option<String>,
     pub desc: Option<String>,
     pub thumbnail: Option<String>,
+    pub is_trash: Option<bool>,
 }
 
 impl TryInto<UpdateViewParams> for UpdateViewRequest {
@@ -71,6 +75,7 @@ impl TryInto<UpdateViewParams> for UpdateViewRequest {
             name,
             desc,
             thumbnail,
+            is_trash: self.is_trash,
         })
     }
 }

+ 3 - 0
rust-lib/flowy-workspace/src/entities/workspace/mod.rs

@@ -5,6 +5,9 @@ pub use workspace_user_detail::*;
 
 pub(crate) mod parser;
 mod workspace_create;
+mod workspace_delete;
 mod workspace_query;
 mod workspace_update;
 mod workspace_user_detail;
+
+pub use workspace_delete::*;

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

@@ -0,0 +1,32 @@
+use crate::{
+    entities::workspace::parser::WorkspaceId,
+    errors::{ErrorBuilder, WorkspaceError, WsErrCode},
+};
+use flowy_derive::ProtoBuf;
+use std::convert::TryInto;
+
+#[derive(Default, ProtoBuf)]
+pub struct DeleteWorkspaceRequest {
+    #[pb(index = 1)]
+    workspace_id: String,
+}
+
+pub struct DeleteWorkspaceParams {
+    workspace_id: String,
+}
+
+impl TryInto<DeleteWorkspaceParams> for DeleteWorkspaceRequest {
+    type Error = WorkspaceError;
+
+    fn try_into(self) -> Result<DeleteWorkspaceParams, Self::Error> {
+        let workspace_id = WorkspaceId::parse(self.workspace_id)
+            .map_err(|e| {
+                ErrorBuilder::new(WsErrCode::WorkspaceIdInvalid)
+                    .msg(e)
+                    .build()
+            })?
+            .0;
+
+        Ok(DeleteWorkspaceParams { workspace_id })
+    }
+}

+ 23 - 7
rust-lib/flowy-workspace/src/event.rs

@@ -8,25 +8,37 @@ pub enum WorkspaceEvent {
     #[event(input = "CreateWorkspaceRequest", output = "Workspace")]
     CreateWorkspace  = 0,
 
-    #[display(fmt = "GetCurWorkspace")]
+    #[display(fmt = "ReadCurWorkspace")]
     #[event(output = "Workspace")]
-    GetCurWorkspace  = 1,
+    ReadCurWorkspace = 1,
 
-    #[display(fmt = "GetWorkspace")]
+    #[display(fmt = "ReadWorkspace")]
     #[event(input = "QueryWorkspaceRequest", output = "Workspace")]
-    GetWorkspace     = 2,
+    ReadWorkspace    = 2,
+
+    #[display(fmt = "DeleteWorkspace")]
+    #[event(input = "DeleteWorkspaceRequest")]
+    DeleteWorkspace  = 3,
 
     #[display(fmt = "ReadAllWorkspace")]
     #[event(output = "Workspaces")]
-    ReadAllWorkspace = 3,
+    ReadAllWorkspace = 4,
 
     #[display(fmt = "CreateApp")]
     #[event(input = "CreateAppRequest", output = "App")]
     CreateApp        = 101,
 
-    #[display(fmt = "GetApp")]
+    #[display(fmt = "DeleteApp")]
+    #[event(input = "DeleteAppRequest")]
+    DeleteApp        = 102,
+
+    #[display(fmt = "ReadApp")]
     #[event(input = "QueryAppRequest", output = "App")]
-    GetApp           = 102,
+    ReadApp          = 103,
+
+    #[display(fmt = "UpdateApp")]
+    #[event(input = "UpdateAppRequest")]
+    UpdateApp        = 104,
 
     #[display(fmt = "CreateView")]
     #[event(input = "CreateViewRequest", output = "View")]
@@ -39,4 +51,8 @@ pub enum WorkspaceEvent {
     #[display(fmt = "UpdateView")]
     #[event(input = "UpdateViewRequest")]
     UpdateView       = 203,
+
+    #[display(fmt = "DeleteView")]
+    #[event(input = "DeleteViewRequest")]
+    DeleteView       = 204,
 }

+ 40 - 7
rust-lib/flowy-workspace/src/handlers/app_handler.rs

@@ -1,10 +1,20 @@
 use crate::{
     entities::{
-        app::{App, CreateAppParams, CreateAppRequest, QueryAppParams, QueryAppRequest},
+        app::{
+            App,
+            CreateAppParams,
+            CreateAppRequest,
+            DeleteAppParams,
+            DeleteAppRequest,
+            QueryAppParams,
+            QueryAppRequest,
+            UpdateAppParams,
+            UpdateAppRequest,
+        },
         view::RepeatedView,
     },
     errors::WorkspaceError,
-    services::AppController,
+    services::{AppController, ViewController},
 };
 use flowy_dispatch::prelude::{response_ok, Data, ResponseResult, Unit};
 use std::{convert::TryInto, sync::Arc};
@@ -19,15 +29,38 @@ pub async fn create_app(
     response_ok(detail)
 }
 
-#[tracing::instrument(name = "get_app", skip(data, controller))]
-pub async fn get_app(
-    data: Data<QueryAppRequest>,
+#[tracing::instrument(name = "delete_app", skip(data, controller))]
+pub async fn delete_app(
+    data: Data<DeleteAppRequest>,
+    controller: Unit<Arc<AppController>>,
+) -> Result<(), WorkspaceError> {
+    let params: DeleteAppParams = data.into_inner().try_into()?;
+    let _ = controller.delete_app(&params.app_id).await?;
+    Ok(())
+}
+
+#[tracing::instrument(name = "update_app", skip(data, controller))]
+pub async fn update_app(
+    data: Data<UpdateAppRequest>,
     controller: Unit<Arc<AppController>>,
+) -> Result<(), WorkspaceError> {
+    let params: UpdateAppParams = data.into_inner().try_into()?;
+    let _ = controller.update_app(params).await?;
+    Ok(())
+}
+
+#[tracing::instrument(name = "read_app", skip(data, app_controller, view_controller))]
+pub async fn read_app(
+    data: Data<QueryAppRequest>,
+    app_controller: Unit<Arc<AppController>>,
+    view_controller: Unit<Arc<ViewController>>,
 ) -> ResponseResult<App, WorkspaceError> {
     let params: QueryAppParams = data.into_inner().try_into()?;
-    let mut app = controller.read_app(&params.app_id).await?;
+    let mut app = app_controller
+        .read_app(&params.app_id, params.is_trash)
+        .await?;
     if params.read_views {
-        let views = controller.read_views(&params.app_id).await?;
+        let views = view_controller.read_views_belong_to(&params.app_id).await?;
         app.views = RepeatedView { items: views };
     }
 

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

@@ -2,6 +2,8 @@ use crate::{
     entities::view::{
         CreateViewParams,
         CreateViewRequest,
+        DeleteViewParams,
+        DeleteViewRequest,
         QueryViewParams,
         QueryViewRequest,
         UpdateViewParams,
@@ -14,6 +16,7 @@ use crate::{
 use flowy_dispatch::prelude::{response_ok, Data, ResponseResult, Unit};
 use std::{convert::TryInto, sync::Arc};
 
+#[tracing::instrument(name = "create_view", skip(data, controller))]
 pub async fn create_view(
     data: Data<CreateViewRequest>,
     controller: Unit<Arc<ViewController>>,
@@ -23,16 +26,20 @@ pub async fn create_view(
     response_ok(view)
 }
 
+#[tracing::instrument(name = "read_view", skip(data, controller))]
 pub async fn read_view(
     data: Data<QueryViewRequest>,
     controller: Unit<Arc<ViewController>>,
 ) -> ResponseResult<View, WorkspaceError> {
     let params: QueryViewParams = data.into_inner().try_into()?;
-    let view = controller.read_view(&params.view_id).await?;
+    let view = controller
+        .read_view(&params.view_id, params.is_trash)
+        .await?;
 
     response_ok(view)
 }
 
+#[tracing::instrument(name = "update_view", skip(data, controller))]
 pub async fn update_view(
     data: Data<UpdateViewRequest>,
     controller: Unit<Arc<ViewController>>,
@@ -42,3 +49,13 @@ pub async fn update_view(
 
     Ok(())
 }
+
+#[tracing::instrument(name = "delete_view", skip(data, controller))]
+pub async fn delete_view(
+    data: Data<DeleteViewRequest>,
+    controller: Unit<Arc<ViewController>>,
+) -> Result<(), WorkspaceError> {
+    let params: DeleteViewParams = data.into_inner().try_into()?;
+    let _ = controller.delete_view(&params.view_id).await?;
+    Ok(())
+}

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

@@ -17,16 +17,16 @@ pub async fn create_workspace(
     response_ok(detail)
 }
 
-#[tracing::instrument(name = "get_cur_workspace", skip(controller))]
-pub async fn get_cur_workspace(
+#[tracing::instrument(name = "read_cur_workspace", skip(controller))]
+pub async fn read_cur_workspace(
     controller: Unit<Arc<WorkspaceController>>,
 ) -> ResponseResult<Workspace, WorkspaceError> {
     let workspace = controller.read_cur_workspace().await?;
     response_ok(workspace)
 }
 
-#[tracing::instrument(name = "get_workspace", skip(data, controller))]
-pub async fn get_workspace(
+#[tracing::instrument(name = "read_workspace", skip(data, controller))]
+pub async fn read_workspace(
     data: Data<QueryWorkspaceRequest>,
     controller: Unit<Arc<WorkspaceController>>,
 ) -> ResponseResult<Workspace, WorkspaceError> {

+ 16 - 5
rust-lib/flowy-workspace/src/module.rs

@@ -37,18 +37,29 @@ pub fn create(user: Arc<dyn WorkspaceUser>, database: Arc<dyn WorkspaceDatabase>
         app_controller.clone(),
     ));
 
-    Module::new()
+    let mut module = Module::new()
         .name("Flowy-Workspace")
         .data(workspace_controller)
         .data(app_controller)
-        .data(view_controller)
+        .data(view_controller);
+
+    module = module
         .event(WorkspaceEvent::ReadAllWorkspace, read_all_workspaces)
         .event(WorkspaceEvent::CreateWorkspace, create_workspace)
-        .event(WorkspaceEvent::GetCurWorkspace, get_cur_workspace)
-        .event(WorkspaceEvent::GetWorkspace, get_workspace)
+        .event(WorkspaceEvent::ReadCurWorkspace, read_cur_workspace)
+        .event(WorkspaceEvent::ReadWorkspace, read_workspace);
+
+    module = module
         .event(WorkspaceEvent::CreateApp, create_app)
-        .event(WorkspaceEvent::GetApp, get_app)
+        .event(WorkspaceEvent::ReadApp, read_app)
+        .event(WorkspaceEvent::UpdateApp, update_app)
+        .event(WorkspaceEvent::DeleteApp, delete_app);
+
+    module = module
         .event(WorkspaceEvent::CreateView, create_view)
         .event(WorkspaceEvent::ReadView, read_view)
         .event(WorkspaceEvent::UpdateView, update_view)
+        .event(WorkspaceEvent::DeleteView, delete_view);
+
+    module
 }

+ 1 - 1
rust-lib/flowy-workspace/src/observable/observable.rs

@@ -46,7 +46,7 @@ impl ObservableSender {
     }
 
     pub(crate) fn send(self) {
-        log::debug!(
+        log::trace!(
             "Workspace observable id: {}, ty: {:?}",
             self.subject_id,
             self.ty

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

@@ -0,0 +1,205 @@
+// 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 `app_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 DeleteAppRequest {
+    // message fields
+    pub app_id: ::std::string::String,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a DeleteAppRequest {
+    fn default() -> &'a DeleteAppRequest {
+        <DeleteAppRequest as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl DeleteAppRequest {
+    pub fn new() -> DeleteAppRequest {
+        ::std::default::Default::default()
+    }
+
+    // string app_id = 1;
+
+
+    pub fn get_app_id(&self) -> &str {
+        &self.app_id
+    }
+    pub fn clear_app_id(&mut self) {
+        self.app_id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_app_id(&mut self, v: ::std::string::String) {
+        self.app_id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_app_id(&mut self) -> &mut ::std::string::String {
+        &mut self.app_id
+    }
+
+    // Take field
+    pub fn take_app_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.app_id, ::std::string::String::new())
+    }
+}
+
+impl ::protobuf::Message for DeleteAppRequest {
+    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.app_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.app_id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.app_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.app_id.is_empty() {
+            os.write_string(1, &self.app_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() -> DeleteAppRequest {
+        DeleteAppRequest::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>(
+                "app_id",
+                |m: &DeleteAppRequest| { &m.app_id },
+                |m: &mut DeleteAppRequest| { &mut m.app_id },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteAppRequest>(
+                "DeleteAppRequest",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static DeleteAppRequest {
+        static instance: ::protobuf::rt::LazyV2<DeleteAppRequest> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(DeleteAppRequest::new)
+    }
+}
+
+impl ::protobuf::Clear for DeleteAppRequest {
+    fn clear(&mut self) {
+        self.app_id.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for DeleteAppRequest {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for DeleteAppRequest {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x10app_delete.proto\")\n\x10DeleteAppRequest\x12\x15\n\x06app_id\x18\
+    \x01\x20\x01(\tR\x05appIdJa\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\x16\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\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15b\
+    \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()
+    })
+}

+ 48 - 9
rust-lib/flowy-workspace/src/protobuf/model/app_query.rs

@@ -28,6 +28,7 @@ pub struct QueryAppRequest {
     // message fields
     pub app_id: ::std::string::String,
     pub read_views: bool,
+    pub is_trash: bool,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -84,6 +85,21 @@ impl QueryAppRequest {
     pub fn set_read_views(&mut self, v: bool) {
         self.read_views = v;
     }
+
+    // bool is_trash = 3;
+
+
+    pub fn get_is_trash(&self) -> bool {
+        self.is_trash
+    }
+    pub fn clear_is_trash(&mut self) {
+        self.is_trash = false;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_is_trash(&mut self, v: bool) {
+        self.is_trash = v;
+    }
 }
 
 impl ::protobuf::Message for QueryAppRequest {
@@ -105,6 +121,13 @@ impl ::protobuf::Message for QueryAppRequest {
                     let tmp = is.read_bool()?;
                     self.read_views = tmp;
                 },
+                3 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_bool()?;
+                    self.is_trash = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -123,6 +146,9 @@ impl ::protobuf::Message for QueryAppRequest {
         if self.read_views != false {
             my_size += 2;
         }
+        if self.is_trash != false {
+            my_size += 2;
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -135,6 +161,9 @@ impl ::protobuf::Message for QueryAppRequest {
         if self.read_views != false {
             os.write_bool(2, self.read_views)?;
         }
+        if self.is_trash != false {
+            os.write_bool(3, self.is_trash)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -183,6 +212,11 @@ impl ::protobuf::Message for QueryAppRequest {
                 |m: &QueryAppRequest| { &m.read_views },
                 |m: &mut QueryAppRequest| { &mut m.read_views },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
+                "is_trash",
+                |m: &QueryAppRequest| { &m.is_trash },
+                |m: &mut QueryAppRequest| { &mut m.is_trash },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<QueryAppRequest>(
                 "QueryAppRequest",
                 fields,
@@ -201,6 +235,7 @@ impl ::protobuf::Clear for QueryAppRequest {
     fn clear(&mut self) {
         self.app_id.clear();
         self.read_views = false;
+        self.is_trash = false;
         self.unknown_fields.clear();
     }
 }
@@ -218,16 +253,20 @@ impl ::protobuf::reflect::ProtobufValue for QueryAppRequest {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0fapp_query.proto\"G\n\x0fQueryAppRequest\x12\x15\n\x06app_id\x18\
+    \n\x0fapp_query.proto\"b\n\x0fQueryAppRequest\x12\x15\n\x06app_id\x18\
     \x01\x20\x01(\tR\x05appId\x12\x1d\n\nread_views\x18\x02\x20\x01(\x08R\tr\
-    eadViewsJ\x98\x01\n\x06\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\
-    \x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\
-    \x02\x08\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x16\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\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\
-    \0\x02\x01\x12\x03\x04\x04\x18\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\
-    \x04\x08\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\t\x13\n\x0c\n\x05\x04\
-    \0\x02\x01\x03\x12\x03\x04\x16\x17b\x06proto3\
+    eadViews\x12\x19\n\x08is_trash\x18\x03\x20\x01(\x08R\x07isTrashJ\xcf\x01\
+    \n\x06\x12\x04\0\0\x06\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\
+    \0\x12\x04\x02\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x17\n\x0b\n\
+    \x04\x04\0\x02\0\x12\x03\x03\x04\x16\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\x11\n\x0c\n\x05\
+    \x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
+    \x04\x04\x18\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\x08\n\x0c\n\
+    \x05\x04\0\x02\x01\x01\x12\x03\x04\t\x13\n\x0c\n\x05\x04\0\x02\x01\x03\
+    \x12\x03\x04\x16\x17\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x16\n\x0c\
+    \n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\x08\n\x0c\n\x05\x04\0\x02\x02\
+    \x01\x12\x03\x05\t\x11\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x14\x15\
+    b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 86 - 24
rust-lib/flowy-workspace/src/protobuf/model/app_update.rs

@@ -32,6 +32,7 @@ pub struct UpdateAppRequest {
     pub one_of_name: ::std::option::Option<UpdateAppRequest_oneof_one_of_name>,
     pub one_of_desc: ::std::option::Option<UpdateAppRequest_oneof_one_of_desc>,
     pub one_of_color_style: ::std::option::Option<UpdateAppRequest_oneof_one_of_color_style>,
+    pub one_of_is_trash: ::std::option::Option<UpdateAppRequest_oneof_one_of_is_trash>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -63,6 +64,11 @@ pub enum UpdateAppRequest_oneof_one_of_color_style {
     color_style(super::app_create::ColorStyle),
 }
 
+#[derive(Clone,PartialEq,Debug)]
+pub enum UpdateAppRequest_oneof_one_of_is_trash {
+    is_trash(bool),
+}
+
 impl UpdateAppRequest {
     pub fn new() -> UpdateAppRequest {
         ::std::default::Default::default()
@@ -289,6 +295,31 @@ impl UpdateAppRequest {
             super::app_create::ColorStyle::new()
         }
     }
+
+    // bool is_trash = 6;
+
+
+    pub fn get_is_trash(&self) -> bool {
+        match self.one_of_is_trash {
+            ::std::option::Option::Some(UpdateAppRequest_oneof_one_of_is_trash::is_trash(v)) => v,
+            _ => false,
+        }
+    }
+    pub fn clear_is_trash(&mut self) {
+        self.one_of_is_trash = ::std::option::Option::None;
+    }
+
+    pub fn has_is_trash(&self) -> bool {
+        match self.one_of_is_trash {
+            ::std::option::Option::Some(UpdateAppRequest_oneof_one_of_is_trash::is_trash(..)) => true,
+            _ => false,
+        }
+    }
+
+    // Param is passed by value, moved
+    pub fn set_is_trash(&mut self, v: bool) {
+        self.one_of_is_trash = ::std::option::Option::Some(UpdateAppRequest_oneof_one_of_is_trash::is_trash(v))
+    }
 }
 
 impl ::protobuf::Message for UpdateAppRequest {
@@ -332,6 +363,12 @@ impl ::protobuf::Message for UpdateAppRequest {
                     }
                     self.one_of_color_style = ::std::option::Option::Some(UpdateAppRequest_oneof_one_of_color_style::color_style(is.read_message()?));
                 },
+                6 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    self.one_of_is_trash = ::std::option::Option::Some(UpdateAppRequest_oneof_one_of_is_trash::is_trash(is.read_bool()?));
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -376,6 +413,13 @@ impl ::protobuf::Message for UpdateAppRequest {
                 },
             };
         }
+        if let ::std::option::Option::Some(ref v) = self.one_of_is_trash {
+            match v {
+                &UpdateAppRequest_oneof_one_of_is_trash::is_trash(v) => {
+                    my_size += 2;
+                },
+            };
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -415,6 +459,13 @@ impl ::protobuf::Message for UpdateAppRequest {
                 },
             };
         }
+        if let ::std::option::Option::Some(ref v) = self.one_of_is_trash {
+            match v {
+                &UpdateAppRequest_oneof_one_of_is_trash::is_trash(v) => {
+                    os.write_bool(6, v)?;
+                },
+            };
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -478,6 +529,11 @@ impl ::protobuf::Message for UpdateAppRequest {
                 UpdateAppRequest::has_color_style,
                 UpdateAppRequest::get_color_style,
             ));
+            fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>(
+                "is_trash",
+                UpdateAppRequest::has_is_trash,
+                UpdateAppRequest::get_is_trash,
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<UpdateAppRequest>(
                 "UpdateAppRequest",
                 fields,
@@ -499,6 +555,7 @@ impl ::protobuf::Clear for UpdateAppRequest {
         self.one_of_name = ::std::option::Option::None;
         self.one_of_desc = ::std::option::Option::None;
         self.one_of_color_style = ::std::option::Option::None;
+        self.one_of_is_trash = ::std::option::Option::None;
         self.unknown_fields.clear();
     }
 }
@@ -516,34 +573,39 @@ impl ::protobuf::reflect::ProtobufValue for UpdateAppRequest {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x10app_update.proto\x1a\x10app_create.proto\"\xf5\x01\n\x10UpdateAppR\
+    \n\x10app_update.proto\x1a\x10app_create.proto\"\xa5\x02\n\x10UpdateAppR\
     equest\x12\x15\n\x06app_id\x18\x01\x20\x01(\tR\x05appId\x12#\n\x0cworksp\
     ace_id\x18\x02\x20\x01(\tH\0R\x0bworkspaceId\x12\x14\n\x04name\x18\x03\
     \x20\x01(\tH\x01R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\x02R\x04\
     desc\x12.\n\x0bcolor_style\x18\x05\x20\x01(\x0b2\x0b.ColorStyleH\x03R\nc\
-    olorStyleB\x15\n\x13one_of_workspace_idB\r\n\x0bone_of_nameB\r\n\x0bone_\
-    of_descB\x14\n\x12one_of_color_styleJ\xb4\x03\n\x06\x12\x04\0\0\t\x01\n\
-    \x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x01\0\x1a\n\n\n\
-    \x02\x04\0\x12\x04\x03\0\t\x01\n\n\n\x03\x04\0\x01\x12\x03\x03\x08\x18\n\
-    \x0b\n\x04\x04\0\x02\0\x12\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\0\x05\
-    \x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x04\x0b\x11\n\x0c\
-    \n\x05\x04\0\x02\0\x03\x12\x03\x04\x14\x15\n\x0b\n\x04\x04\0\x08\0\x12\
-    \x03\x05\x04:\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x05\n\x1d\n\x0b\n\x04\
-    \x04\0\x02\x01\x12\x03\x05\x208\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\
-    \x05\x20&\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x05'3\n\x0c\n\x05\x04\0\
-    \x02\x01\x03\x12\x03\x0567\n\x0b\n\x04\x04\0\x08\x01\x12\x03\x06\x04*\n\
-    \x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x06\n\x15\n\x0b\n\x04\x04\0\x02\x02\
-    \x12\x03\x06\x18(\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x06\x18\x1e\n\
-    \x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x06\x1f#\n\x0c\n\x05\x04\0\x02\x02\
-    \x03\x12\x03\x06&'\n\x0b\n\x04\x04\0\x08\x02\x12\x03\x07\x04*\n\x0c\n\
-    \x05\x04\0\x08\x02\x01\x12\x03\x07\n\x15\n\x0b\n\x04\x04\0\x02\x03\x12\
-    \x03\x07\x18(\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x07\x18\x1e\n\x0c\n\
-    \x05\x04\0\x02\x03\x01\x12\x03\x07\x1f#\n\x0c\n\x05\x04\0\x02\x03\x03\
-    \x12\x03\x07&'\n\x0b\n\x04\x04\0\x08\x03\x12\x03\x08\x04<\n\x0c\n\x05\
-    \x04\0\x08\x03\x01\x12\x03\x08\n\x1c\n\x0b\n\x04\x04\0\x02\x04\x12\x03\
-    \x08\x1f:\n\x0c\n\x05\x04\0\x02\x04\x06\x12\x03\x08\x1f)\n\x0c\n\x05\x04\
-    \0\x02\x04\x01\x12\x03\x08*5\n\x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x0889\
-    b\x06proto3\
+    olorStyle\x12\x1b\n\x08is_trash\x18\x06\x20\x01(\x08H\x04R\x07isTrashB\
+    \x15\n\x13one_of_workspace_idB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\
+    \x14\n\x12one_of_color_styleB\x11\n\x0fone_of_is_trashJ\x86\x04\n\x06\
+    \x12\x04\0\0\n\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\
+    \x03\x01\0\x1a\n\n\n\x02\x04\0\x12\x04\x03\0\n\x01\n\n\n\x03\x04\0\x01\
+    \x12\x03\x03\x08\x18\n\x0b\n\x04\x04\0\x02\0\x12\x03\x04\x04\x16\n\x0c\n\
+    \x05\x04\0\x02\0\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\
+    \x03\x04\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x04\x14\x15\n\x0b\n\
+    \x04\x04\0\x08\0\x12\x03\x05\x04:\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\
+    \x05\n\x1d\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x05\x208\n\x0c\n\x05\x04\0\
+    \x02\x01\x05\x12\x03\x05\x20&\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x05'\
+    3\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x0567\n\x0b\n\x04\x04\0\x08\x01\
+    \x12\x03\x06\x04*\n\x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x06\n\x15\n\x0b\
+    \n\x04\x04\0\x02\x02\x12\x03\x06\x18(\n\x0c\n\x05\x04\0\x02\x02\x05\x12\
+    \x03\x06\x18\x1e\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x06\x1f#\n\x0c\n\
+    \x05\x04\0\x02\x02\x03\x12\x03\x06&'\n\x0b\n\x04\x04\0\x08\x02\x12\x03\
+    \x07\x04*\n\x0c\n\x05\x04\0\x08\x02\x01\x12\x03\x07\n\x15\n\x0b\n\x04\
+    \x04\0\x02\x03\x12\x03\x07\x18(\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\
+    \x07\x18\x1e\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x07\x1f#\n\x0c\n\x05\
+    \x04\0\x02\x03\x03\x12\x03\x07&'\n\x0b\n\x04\x04\0\x08\x03\x12\x03\x08\
+    \x04<\n\x0c\n\x05\x04\0\x08\x03\x01\x12\x03\x08\n\x1c\n\x0b\n\x04\x04\0\
+    \x02\x04\x12\x03\x08\x1f:\n\x0c\n\x05\x04\0\x02\x04\x06\x12\x03\x08\x1f)\
+    \n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x08*5\n\x0c\n\x05\x04\0\x02\x04\
+    \x03\x12\x03\x0889\n\x0b\n\x04\x04\0\x08\x04\x12\x03\t\x040\n\x0c\n\x05\
+    \x04\0\x08\x04\x01\x12\x03\t\n\x19\n\x0b\n\x04\x04\0\x02\x05\x12\x03\t\
+    \x1c.\n\x0c\n\x05\x04\0\x02\x05\x05\x12\x03\t\x1c\x20\n\x0c\n\x05\x04\0\
+    \x02\x05\x01\x12\x03\t!)\n\x0c\n\x05\x04\0\x02\x05\x03\x12\x03\t,-b\x06p\
+    roto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 58 - 37
rust-lib/flowy-workspace/src/protobuf/model/event.rs

@@ -26,14 +26,18 @@
 #[derive(Clone,PartialEq,Eq,Debug,Hash)]
 pub enum WorkspaceEvent {
     CreateWorkspace = 0,
-    GetCurWorkspace = 1,
-    GetWorkspace = 2,
-    ReadAllWorkspace = 3,
+    ReadCurWorkspace = 1,
+    ReadWorkspace = 2,
+    DeleteWorkspace = 3,
+    ReadAllWorkspace = 4,
     CreateApp = 101,
-    GetApp = 102,
+    DeleteApp = 102,
+    ReadApp = 103,
+    UpdateApp = 104,
     CreateView = 201,
     ReadView = 202,
     UpdateView = 203,
+    DeleteView = 204,
 }
 
 impl ::protobuf::ProtobufEnum for WorkspaceEvent {
@@ -44,14 +48,18 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent {
     fn from_i32(value: i32) -> ::std::option::Option<WorkspaceEvent> {
         match value {
             0 => ::std::option::Option::Some(WorkspaceEvent::CreateWorkspace),
-            1 => ::std::option::Option::Some(WorkspaceEvent::GetCurWorkspace),
-            2 => ::std::option::Option::Some(WorkspaceEvent::GetWorkspace),
-            3 => ::std::option::Option::Some(WorkspaceEvent::ReadAllWorkspace),
+            1 => ::std::option::Option::Some(WorkspaceEvent::ReadCurWorkspace),
+            2 => ::std::option::Option::Some(WorkspaceEvent::ReadWorkspace),
+            3 => ::std::option::Option::Some(WorkspaceEvent::DeleteWorkspace),
+            4 => ::std::option::Option::Some(WorkspaceEvent::ReadAllWorkspace),
             101 => ::std::option::Option::Some(WorkspaceEvent::CreateApp),
-            102 => ::std::option::Option::Some(WorkspaceEvent::GetApp),
+            102 => ::std::option::Option::Some(WorkspaceEvent::DeleteApp),
+            103 => ::std::option::Option::Some(WorkspaceEvent::ReadApp),
+            104 => ::std::option::Option::Some(WorkspaceEvent::UpdateApp),
             201 => ::std::option::Option::Some(WorkspaceEvent::CreateView),
             202 => ::std::option::Option::Some(WorkspaceEvent::ReadView),
             203 => ::std::option::Option::Some(WorkspaceEvent::UpdateView),
+            204 => ::std::option::Option::Some(WorkspaceEvent::DeleteView),
             _ => ::std::option::Option::None
         }
     }
@@ -59,14 +67,18 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent {
     fn values() -> &'static [Self] {
         static values: &'static [WorkspaceEvent] = &[
             WorkspaceEvent::CreateWorkspace,
-            WorkspaceEvent::GetCurWorkspace,
-            WorkspaceEvent::GetWorkspace,
+            WorkspaceEvent::ReadCurWorkspace,
+            WorkspaceEvent::ReadWorkspace,
+            WorkspaceEvent::DeleteWorkspace,
             WorkspaceEvent::ReadAllWorkspace,
             WorkspaceEvent::CreateApp,
-            WorkspaceEvent::GetApp,
+            WorkspaceEvent::DeleteApp,
+            WorkspaceEvent::ReadApp,
+            WorkspaceEvent::UpdateApp,
             WorkspaceEvent::CreateView,
             WorkspaceEvent::ReadView,
             WorkspaceEvent::UpdateView,
+            WorkspaceEvent::DeleteView,
         ];
         values
     }
@@ -95,32 +107,41 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceEvent {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0bevent.proto*\xae\x01\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorksp\
-    ace\x10\0\x12\x13\n\x0fGetCurWorkspace\x10\x01\x12\x10\n\x0cGetWorkspace\
-    \x10\x02\x12\x14\n\x10ReadAllWorkspace\x10\x03\x12\r\n\tCreateApp\x10e\
-    \x12\n\n\x06GetApp\x10f\x12\x0f\n\nCreateView\x10\xc9\x01\x12\r\n\x08Rea\
-    dView\x10\xca\x01\x12\x0f\n\nUpdateView\x10\xcb\x01J\x9b\x03\n\x06\x12\
-    \x04\0\0\x0c\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\
-    \x02\0\x0c\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x13\n\x0b\n\x04\x05\0\
-    \x02\0\x12\x03\x03\x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\
-    \x13\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x16\x17\n\x0b\n\x04\x05\0\
-    \x02\x01\x12\x03\x04\x04\x18\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\
-    \x04\x13\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x16\x17\n\x0b\n\x04\
-    \x05\0\x02\x02\x12\x03\x05\x04\x15\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\
-    \x05\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\x13\x14\n\x0b\n\
-    \x04\x05\0\x02\x03\x12\x03\x06\x04\x19\n\x0c\n\x05\x05\0\x02\x03\x01\x12\
-    \x03\x06\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x17\x18\n\x0b\
-    \n\x04\x05\0\x02\x04\x12\x03\x07\x04\x14\n\x0c\n\x05\x05\0\x02\x04\x01\
-    \x12\x03\x07\x04\r\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x10\x13\n\
-    \x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x11\n\x0c\n\x05\x05\0\x02\x05\
-    \x01\x12\x03\x08\x04\n\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\r\x10\n\
-    \x0b\n\x04\x05\0\x02\x06\x12\x03\t\x04\x15\n\x0c\n\x05\x05\0\x02\x06\x01\
-    \x12\x03\t\x04\x0e\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x11\x14\n\x0b\
-    \n\x04\x05\0\x02\x07\x12\x03\n\x04\x13\n\x0c\n\x05\x05\0\x02\x07\x01\x12\
-    \x03\n\x04\x0c\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x0f\x12\n\x0b\n\
-    \x04\x05\0\x02\x08\x12\x03\x0b\x04\x15\n\x0c\n\x05\x05\0\x02\x08\x01\x12\
-    \x03\x0b\x04\x0e\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x11\x14b\x06p\
-    roto3\
+    \n\x0bevent.proto*\xf5\x01\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorksp\
+    ace\x10\0\x12\x14\n\x10ReadCurWorkspace\x10\x01\x12\x11\n\rReadWorkspace\
+    \x10\x02\x12\x13\n\x0fDeleteWorkspace\x10\x03\x12\x14\n\x10ReadAllWorksp\
+    ace\x10\x04\x12\r\n\tCreateApp\x10e\x12\r\n\tDeleteApp\x10f\x12\x0b\n\
+    \x07ReadApp\x10g\x12\r\n\tUpdateApp\x10h\x12\x0f\n\nCreateView\x10\xc9\
+    \x01\x12\r\n\x08ReadView\x10\xca\x01\x12\x0f\n\nUpdateView\x10\xcb\x01\
+    \x12\x0f\n\nDeleteView\x10\xcc\x01J\xbf\x04\n\x06\x12\x04\0\0\x10\x01\n\
+    \x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x10\x01\n\n\
+    \n\x03\x05\0\x01\x12\x03\x02\x05\x13\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\
+    \x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x13\n\x0c\n\x05\x05\
+    \0\x02\0\x02\x12\x03\x03\x16\x17\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\
+    \x04\x19\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\
+    \x05\0\x02\x01\x02\x12\x03\x04\x17\x18\n\x0b\n\x04\x05\0\x02\x02\x12\x03\
+    \x05\x04\x16\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\x11\n\x0c\n\
+    \x05\x05\0\x02\x02\x02\x12\x03\x05\x14\x15\n\x0b\n\x04\x05\0\x02\x03\x12\
+    \x03\x06\x04\x18\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x13\n\x0c\
+    \n\x05\x05\0\x02\x03\x02\x12\x03\x06\x16\x17\n\x0b\n\x04\x05\0\x02\x04\
+    \x12\x03\x07\x04\x19\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x14\n\
+    \x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x17\x18\n\x0b\n\x04\x05\0\x02\
+    \x05\x12\x03\x08\x04\x14\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\r\
+    \n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x10\x13\n\x0b\n\x04\x05\0\x02\
+    \x06\x12\x03\t\x04\x14\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\x04\r\n\
+    \x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x10\x13\n\x0b\n\x04\x05\0\x02\x07\
+    \x12\x03\n\x04\x12\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\x0b\n\x0c\
+    \n\x05\x05\0\x02\x07\x02\x12\x03\n\x0e\x11\n\x0b\n\x04\x05\0\x02\x08\x12\
+    \x03\x0b\x04\x14\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0b\x04\r\n\x0c\n\
+    \x05\x05\0\x02\x08\x02\x12\x03\x0b\x10\x13\n\x0b\n\x04\x05\0\x02\t\x12\
+    \x03\x0c\x04\x15\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x0c\x04\x0e\n\x0c\n\
+    \x05\x05\0\x02\t\x02\x12\x03\x0c\x11\x14\n\x0b\n\x04\x05\0\x02\n\x12\x03\
+    \r\x04\x13\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\r\x04\x0c\n\x0c\n\x05\x05\
+    \0\x02\n\x02\x12\x03\r\x0f\x12\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x0e\x04\
+    \x15\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x0e\x04\x0e\n\x0c\n\x05\x05\0\
+    \x02\x0b\x02\x12\x03\x0e\x11\x14\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x0f\
+    \x04\x15\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x0f\x04\x0e\n\x0c\n\x05\
+    \x05\0\x02\x0c\x02\x12\x03\x0f\x11\x14b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 9 - 0
rust-lib/flowy-workspace/src/protobuf/model/mod.rs

@@ -3,9 +3,15 @@
 mod view_update; 
 pub use view_update::*; 
 
+mod view_delete; 
+pub use view_delete::*; 
+
 mod app_query; 
 pub use app_query::*; 
 
+mod workspace_delete; 
+pub use workspace_delete::*; 
+
 mod observable; 
 pub use observable::*; 
 
@@ -38,3 +44,6 @@ pub use app_update::*;
 
 mod view_query; 
 pub use view_query::*; 
+
+mod app_delete; 
+pub use app_delete::*; 

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

@@ -0,0 +1,205 @@
+// 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 `view_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 DeleteViewRequest {
+    // message fields
+    pub view_id: ::std::string::String,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a DeleteViewRequest {
+    fn default() -> &'a DeleteViewRequest {
+        <DeleteViewRequest as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl DeleteViewRequest {
+    pub fn new() -> DeleteViewRequest {
+        ::std::default::Default::default()
+    }
+
+    // string view_id = 1;
+
+
+    pub fn get_view_id(&self) -> &str {
+        &self.view_id
+    }
+    pub fn clear_view_id(&mut self) {
+        self.view_id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_view_id(&mut self, v: ::std::string::String) {
+        self.view_id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_view_id(&mut self) -> &mut ::std::string::String {
+        &mut self.view_id
+    }
+
+    // Take field
+    pub fn take_view_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.view_id, ::std::string::String::new())
+    }
+}
+
+impl ::protobuf::Message for DeleteViewRequest {
+    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.view_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.view_id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.view_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.view_id.is_empty() {
+            os.write_string(1, &self.view_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() -> DeleteViewRequest {
+        DeleteViewRequest::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>(
+                "view_id",
+                |m: &DeleteViewRequest| { &m.view_id },
+                |m: &mut DeleteViewRequest| { &mut m.view_id },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteViewRequest>(
+                "DeleteViewRequest",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static DeleteViewRequest {
+        static instance: ::protobuf::rt::LazyV2<DeleteViewRequest> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(DeleteViewRequest::new)
+    }
+}
+
+impl ::protobuf::Clear for DeleteViewRequest {
+    fn clear(&mut self) {
+        self.view_id.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for DeleteViewRequest {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for DeleteViewRequest {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x11view_delete.proto\",\n\x11DeleteViewRequest\x12\x17\n\x07view_id\
+    \x18\x01\x20\x01(\tR\x06viewIdJa\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\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x17\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\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\x16b\
+    \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()
+    })
+}

+ 45 - 7
rust-lib/flowy-workspace/src/protobuf/model/view_query.rs

@@ -27,6 +27,7 @@
 pub struct QueryViewRequest {
     // message fields
     pub view_id: ::std::string::String,
+    pub is_trash: bool,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -68,6 +69,21 @@ impl QueryViewRequest {
     pub fn take_view_id(&mut self) -> ::std::string::String {
         ::std::mem::replace(&mut self.view_id, ::std::string::String::new())
     }
+
+    // bool is_trash = 2;
+
+
+    pub fn get_is_trash(&self) -> bool {
+        self.is_trash
+    }
+    pub fn clear_is_trash(&mut self) {
+        self.is_trash = false;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_is_trash(&mut self, v: bool) {
+        self.is_trash = v;
+    }
 }
 
 impl ::protobuf::Message for QueryViewRequest {
@@ -82,6 +98,13 @@ impl ::protobuf::Message for QueryViewRequest {
                 1 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?;
                 },
+                2 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_bool()?;
+                    self.is_trash = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -97,6 +120,9 @@ impl ::protobuf::Message for QueryViewRequest {
         if !self.view_id.is_empty() {
             my_size += ::protobuf::rt::string_size(1, &self.view_id);
         }
+        if self.is_trash != false {
+            my_size += 2;
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -106,6 +132,9 @@ impl ::protobuf::Message for QueryViewRequest {
         if !self.view_id.is_empty() {
             os.write_string(1, &self.view_id)?;
         }
+        if self.is_trash != false {
+            os.write_bool(2, self.is_trash)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -149,6 +178,11 @@ impl ::protobuf::Message for QueryViewRequest {
                 |m: &QueryViewRequest| { &m.view_id },
                 |m: &mut QueryViewRequest| { &mut m.view_id },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
+                "is_trash",
+                |m: &QueryViewRequest| { &m.is_trash },
+                |m: &mut QueryViewRequest| { &mut m.is_trash },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<QueryViewRequest>(
                 "QueryViewRequest",
                 fields,
@@ -166,6 +200,7 @@ impl ::protobuf::Message for QueryViewRequest {
 impl ::protobuf::Clear for QueryViewRequest {
     fn clear(&mut self) {
         self.view_id.clear();
+        self.is_trash = false;
         self.unknown_fields.clear();
     }
 }
@@ -183,13 +218,16 @@ impl ::protobuf::reflect::ProtobufValue for QueryViewRequest {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x10view_query.proto\"+\n\x10QueryViewRequest\x12\x17\n\x07view_id\x18\
-    \x01\x20\x01(\tR\x06viewIdJa\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\x17\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\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\x16b\
-    \x06proto3\
+    \n\x10view_query.proto\"F\n\x10QueryViewRequest\x12\x17\n\x07view_id\x18\
+    \x01\x20\x01(\tR\x06viewId\x12\x19\n\x08is_trash\x18\x02\x20\x01(\x08R\
+    \x07isTrashJ\x98\x01\n\x06\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\
+    \0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\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\x17\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\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\x16\n\x0b\n\x04\x04\
+    \0\x02\x01\x12\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\
+    \x04\x08\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\t\x11\n\x0c\n\x05\x04\
+    \0\x02\x01\x03\x12\x03\x04\x14\x15b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 82 - 19
rust-lib/flowy-workspace/src/protobuf/model/view_update.rs

@@ -31,6 +31,7 @@ pub struct UpdateViewRequest {
     pub one_of_name: ::std::option::Option<UpdateViewRequest_oneof_one_of_name>,
     pub one_of_desc: ::std::option::Option<UpdateViewRequest_oneof_one_of_desc>,
     pub one_of_thumbnail: ::std::option::Option<UpdateViewRequest_oneof_one_of_thumbnail>,
+    pub one_of_is_trash: ::std::option::Option<UpdateViewRequest_oneof_one_of_is_trash>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -57,6 +58,11 @@ pub enum UpdateViewRequest_oneof_one_of_thumbnail {
     thumbnail(::std::string::String),
 }
 
+#[derive(Clone,PartialEq,Debug)]
+pub enum UpdateViewRequest_oneof_one_of_is_trash {
+    is_trash(bool),
+}
+
 impl UpdateViewRequest {
     pub fn new() -> UpdateViewRequest {
         ::std::default::Default::default()
@@ -234,6 +240,31 @@ impl UpdateViewRequest {
             ::std::string::String::new()
         }
     }
+
+    // bool is_trash = 5;
+
+
+    pub fn get_is_trash(&self) -> bool {
+        match self.one_of_is_trash {
+            ::std::option::Option::Some(UpdateViewRequest_oneof_one_of_is_trash::is_trash(v)) => v,
+            _ => false,
+        }
+    }
+    pub fn clear_is_trash(&mut self) {
+        self.one_of_is_trash = ::std::option::Option::None;
+    }
+
+    pub fn has_is_trash(&self) -> bool {
+        match self.one_of_is_trash {
+            ::std::option::Option::Some(UpdateViewRequest_oneof_one_of_is_trash::is_trash(..)) => true,
+            _ => false,
+        }
+    }
+
+    // Param is passed by value, moved
+    pub fn set_is_trash(&mut self, v: bool) {
+        self.one_of_is_trash = ::std::option::Option::Some(UpdateViewRequest_oneof_one_of_is_trash::is_trash(v))
+    }
 }
 
 impl ::protobuf::Message for UpdateViewRequest {
@@ -266,6 +297,12 @@ impl ::protobuf::Message for UpdateViewRequest {
                     }
                     self.one_of_thumbnail = ::std::option::Option::Some(UpdateViewRequest_oneof_one_of_thumbnail::thumbnail(is.read_string()?));
                 },
+                5 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    self.one_of_is_trash = ::std::option::Option::Some(UpdateViewRequest_oneof_one_of_is_trash::is_trash(is.read_bool()?));
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -302,6 +339,13 @@ impl ::protobuf::Message for UpdateViewRequest {
                 },
             };
         }
+        if let ::std::option::Option::Some(ref v) = self.one_of_is_trash {
+            match v {
+                &UpdateViewRequest_oneof_one_of_is_trash::is_trash(v) => {
+                    my_size += 2;
+                },
+            };
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -332,6 +376,13 @@ impl ::protobuf::Message for UpdateViewRequest {
                 },
             };
         }
+        if let ::std::option::Option::Some(ref v) = self.one_of_is_trash {
+            match v {
+                &UpdateViewRequest_oneof_one_of_is_trash::is_trash(v) => {
+                    os.write_bool(5, v)?;
+                },
+            };
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -390,6 +441,11 @@ impl ::protobuf::Message for UpdateViewRequest {
                 UpdateViewRequest::has_thumbnail,
                 UpdateViewRequest::get_thumbnail,
             ));
+            fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>(
+                "is_trash",
+                UpdateViewRequest::has_is_trash,
+                UpdateViewRequest::get_is_trash,
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<UpdateViewRequest>(
                 "UpdateViewRequest",
                 fields,
@@ -410,6 +466,7 @@ impl ::protobuf::Clear for UpdateViewRequest {
         self.one_of_name = ::std::option::Option::None;
         self.one_of_desc = ::std::option::Option::None;
         self.one_of_thumbnail = ::std::option::Option::None;
+        self.one_of_is_trash = ::std::option::Option::None;
         self.unknown_fields.clear();
     }
 }
@@ -427,27 +484,33 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewRequest {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x11view_update.proto\"\xaa\x01\n\x11UpdateViewRequest\x12\x17\n\x07vi\
+    \n\x11view_update.proto\"\xda\x01\n\x11UpdateViewRequest\x12\x17\n\x07vi\
     ew_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\t\
     H\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\
-    \n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\
-    \n\x0bone_of_descB\x12\n\x10one_of_thumbnailJ\xd7\x02\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\
-    \x07\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\
-    \x12\x03\x03\x04\x17\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\x12\n\x0c\n\x05\x04\0\x02\0\x03\
-    \x12\x03\x03\x15\x16\n\x0b\n\x04\x04\0\x08\0\x12\x03\x04\x04*\n\x0c\n\
-    \x05\x04\0\x08\0\x01\x12\x03\x04\n\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
-    \x04\x18(\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x18\x1e\n\x0c\n\x05\
-    \x04\0\x02\x01\x01\x12\x03\x04\x1f#\n\x0c\n\x05\x04\0\x02\x01\x03\x12\
-    \x03\x04&'\n\x0b\n\x04\x04\0\x08\x01\x12\x03\x05\x04*\n\x0c\n\x05\x04\0\
-    \x08\x01\x01\x12\x03\x05\n\x15\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x18\
-    (\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x18\x1e\n\x0c\n\x05\x04\0\
-    \x02\x02\x01\x12\x03\x05\x1f#\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05&\
-    '\n\x0b\n\x04\x04\0\x08\x02\x12\x03\x06\x044\n\x0c\n\x05\x04\0\x08\x02\
-    \x01\x12\x03\x06\n\x1a\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\
-    \n\x05\x04\0\x02\x03\x05\x12\x03\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\
-    \x12\x03\x06$-\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x0601b\x06proto3\
+    \n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnail\x12\x1b\n\x08is_trash\
+    \x18\x05\x20\x01(\x08H\x03R\x07isTrashB\r\n\x0bone_of_nameB\r\n\x0bone_o\
+    f_descB\x12\n\x10one_of_thumbnailB\x11\n\x0fone_of_is_trashJ\xa9\x03\n\
+    \x06\x12\x04\0\0\x08\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
+    \x12\x04\x02\0\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\
+    \x04\x04\0\x02\0\x12\x03\x03\x04\x17\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\x12\n\x0c\n\x05\
+    \x04\0\x02\0\x03\x12\x03\x03\x15\x16\n\x0b\n\x04\x04\0\x08\0\x12\x03\x04\
+    \x04*\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x04\n\x15\n\x0b\n\x04\x04\0\
+    \x02\x01\x12\x03\x04\x18(\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x18\
+    \x1e\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x1f#\n\x0c\n\x05\x04\0\
+    \x02\x01\x03\x12\x03\x04&'\n\x0b\n\x04\x04\0\x08\x01\x12\x03\x05\x04*\n\
+    \x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x05\n\x15\n\x0b\n\x04\x04\0\x02\x02\
+    \x12\x03\x05\x18(\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x18\x1e\n\
+    \x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x1f#\n\x0c\n\x05\x04\0\x02\x02\
+    \x03\x12\x03\x05&'\n\x0b\n\x04\x04\0\x08\x02\x12\x03\x06\x044\n\x0c\n\
+    \x05\x04\0\x08\x02\x01\x12\x03\x06\n\x1a\n\x0b\n\x04\x04\0\x02\x03\x12\
+    \x03\x06\x1d2\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x06\x1d#\n\x0c\n\x05\
+    \x04\0\x02\x03\x01\x12\x03\x06$-\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\
+    \x0601\n\x0b\n\x04\x04\0\x08\x03\x12\x03\x07\x040\n\x0c\n\x05\x04\0\x08\
+    \x03\x01\x12\x03\x07\n\x19\n\x0b\n\x04\x04\0\x02\x04\x12\x03\x07\x1c.\n\
+    \x0c\n\x05\x04\0\x02\x04\x05\x12\x03\x07\x1c\x20\n\x0c\n\x05\x04\0\x02\
+    \x04\x01\x12\x03\x07!)\n\x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x07,-b\x06p\
+    roto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

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

@@ -0,0 +1,205 @@
+// 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)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x16workspace_delete.proto\";\n\x16DeleteWorkspaceRequest\x12!\n\x0cwo\
+    rkspace_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\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\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()
+    })
+}

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

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

+ 1 - 0
rust-lib/flowy-workspace/src/protobuf/proto/app_query.proto

@@ -3,4 +3,5 @@ syntax = "proto3";
 message QueryAppRequest {
     string app_id = 1;
     bool read_views = 2;
+    bool is_trash = 3;
 }

+ 1 - 0
rust-lib/flowy-workspace/src/protobuf/proto/app_update.proto

@@ -7,4 +7,5 @@ message UpdateAppRequest {
     oneof one_of_name { string name = 3; };
     oneof one_of_desc { string desc = 4; };
     oneof one_of_color_style { ColorStyle color_style = 5; };
+    oneof one_of_is_trash { bool is_trash = 6; };
 }

+ 8 - 4
rust-lib/flowy-workspace/src/protobuf/proto/event.proto

@@ -2,12 +2,16 @@ syntax = "proto3";
 
 enum WorkspaceEvent {
     CreateWorkspace = 0;
-    GetCurWorkspace = 1;
-    GetWorkspace = 2;
-    ReadAllWorkspace = 3;
+    ReadCurWorkspace = 1;
+    ReadWorkspace = 2;
+    DeleteWorkspace = 3;
+    ReadAllWorkspace = 4;
     CreateApp = 101;
-    GetApp = 102;
+    DeleteApp = 102;
+    ReadApp = 103;
+    UpdateApp = 104;
     CreateView = 201;
     ReadView = 202;
     UpdateView = 203;
+    DeleteView = 204;
 }

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

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

+ 1 - 0
rust-lib/flowy-workspace/src/protobuf/proto/view_query.proto

@@ -2,4 +2,5 @@ syntax = "proto3";
 
 message QueryViewRequest {
     string view_id = 1;
+    bool is_trash = 2;
 }

+ 1 - 0
rust-lib/flowy-workspace/src/protobuf/proto/view_update.proto

@@ -5,4 +5,5 @@ message UpdateViewRequest {
     oneof one_of_name { string name = 2; };
     oneof one_of_desc { string desc = 3; };
     oneof one_of_thumbnail { string thumbnail = 4; };
+    oneof one_of_is_trash { bool is_trash = 5; };
 }

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

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

+ 14 - 16
rust-lib/flowy-workspace/src/services/app_controller.rs

@@ -40,12 +40,17 @@ impl AppController {
         Ok(app)
     }
 
-    pub async fn read_app(&self, app_id: &str) -> Result<App, WorkspaceError> {
-        let app_table = self.async_read_app(&app_id).await?;
+    pub async fn read_app(&self, app_id: &str, is_trash: bool) -> Result<App, WorkspaceError> {
+        let app_table = self.async_read_app(&app_id, is_trash).await?;
         Ok(app_table.into())
     }
 
-    pub fn update_app(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
+    pub async fn delete_app(&self, app_id: &str) -> Result<(), WorkspaceError> {
+        let _ = self.sql.delete_app(app_id)?;
+        Ok(())
+    }
+
+    pub async fn update_app(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
         let changeset = AppTableChangeset::new(params);
         let app_id = changeset.id.clone();
         let _ = self.sql.update_app(changeset)?;
@@ -53,23 +58,16 @@ impl AppController {
         Ok(())
     }
 
-    pub async fn read_views(&self, app_id: &str) -> Result<Vec<View>, WorkspaceError> {
-        let views = self
-            .sql
-            .read_views_belong_to_app(app_id)?
-            .into_iter()
-            .map(|view_table| view_table.into())
-            .collect::<Vec<View>>();
-
-        Ok(views)
-    }
-
-    fn async_read_app(&self, app_id: &str) -> DispatchFuture<Result<AppTable, WorkspaceError>> {
+    fn async_read_app(
+        &self,
+        app_id: &str,
+        is_trash: bool,
+    ) -> DispatchFuture<Result<AppTable, WorkspaceError>> {
         let sql = self.sql.clone();
         let app_id = app_id.to_owned();
         DispatchFuture {
             fut: Box::pin(async move {
-                let app_table = sql.read_app(&app_id)?;
+                let app_table = sql.read_app(&app_id, is_trash)?;
                 // TODO: fetch app from remote server
                 Ok(app_table)
             }),

+ 21 - 2
rust-lib/flowy-workspace/src/services/view_controller.rs

@@ -26,12 +26,31 @@ impl ViewController {
         Ok(view)
     }
 
-    pub async fn read_view(&self, view_id: &str) -> Result<View, WorkspaceError> {
-        let view_table = self.sql.read_view(view_id)?;
+    pub async fn read_view(&self, view_id: &str, is_trash: bool) -> Result<View, WorkspaceError> {
+        let view_table = self.sql.read_view(view_id, is_trash)?;
         let view: View = view_table.into();
         Ok(view)
     }
 
+    pub async fn delete_view(&self, view_id: &str) -> Result<(), WorkspaceError> {
+        let _ = self.sql.delete_view(view_id)?;
+        Ok(())
+    }
+
+    pub async fn read_views_belong_to(
+        &self,
+        belong_to_id: &str,
+    ) -> Result<Vec<View>, WorkspaceError> {
+        let views = self
+            .sql
+            .read_views_belong_to(belong_to_id)?
+            .into_iter()
+            .map(|view_table| view_table.into())
+            .collect::<Vec<View>>();
+
+        Ok(views)
+    }
+
     pub async fn update_view(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
         let changeset = ViewTableChangeset::new(params);
         let view_id = changeset.id.clone();

+ 27 - 19
rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs

@@ -31,32 +31,40 @@ impl AppTableSql {
         Ok(())
     }
 
-    pub(crate) fn read_app(&self, app_id: &str) -> Result<AppTable, WorkspaceError> {
+    pub(crate) fn read_app(
+        &self,
+        app_id: &str,
+        is_trash: bool,
+    ) -> Result<AppTable, WorkspaceError> {
         let app_table = dsl::app_table
             .filter(app_table::id.eq(app_id))
+            .filter(app_table::is_trash.eq(is_trash))
             .first::<AppTable>(&*(self.database.db_connection()?))?;
 
         Ok(app_table)
     }
 
-    pub(crate) fn delete_app(&self, _app_id: &str) -> Result<(), WorkspaceError> {
-        unimplemented!()
-    }
-
-    pub(crate) fn read_views_belong_to_app(
-        &self,
-        app_id: &str,
-    ) -> Result<Vec<ViewTable>, WorkspaceError> {
+    pub(crate) fn delete_app(&self, app_id: &str) -> Result<(), WorkspaceError> {
         let conn = self.database.db_connection()?;
-
-        let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
-            let app_table: AppTable = dsl::app_table
-                .filter(app_table::id.eq(app_id))
-                .first::<AppTable>(&*(conn))?;
-            let views = ViewTable::belonging_to(&app_table).load::<ViewTable>(&*conn)?;
-            Ok(views)
-        })?;
-
-        Ok(views)
+        diesel_delete_table!(app_table, app_id, conn);
+        Ok(())
     }
+
+    // pub(crate) fn read_views_belong_to_app(
+    //     &self,
+    //     app_id: &str,
+    // ) -> Result<Vec<ViewTable>, WorkspaceError> {
+    //     let conn = self.database.db_connection()?;
+    //
+    //     let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
+    //         let app_table: AppTable = dsl::app_table
+    //             .filter(app_table::id.eq(app_id))
+    //             .first::<AppTable>(&*(conn))?;
+    //         let views =
+    // ViewTable::belonging_to(&app_table).load::<ViewTable>(&*conn)?;
+    //         Ok(views)
+    //     })?;
+    //
+    //     Ok(views)
+    // }
 }

+ 4 - 0
rust-lib/flowy-workspace/src/sql_tables/app/app_table.rs

@@ -25,6 +25,7 @@ pub(crate) struct AppTable {
     pub modified_time: i64,
     pub create_time: i64,
     pub version: i64,
+    pub is_trash: bool,
 }
 
 impl AppTable {
@@ -41,6 +42,7 @@ impl AppTable {
             modified_time: time,
             create_time: time,
             version: 0,
+            is_trash: false,
         }
     }
 }
@@ -84,6 +86,7 @@ pub struct AppTableChangeset {
     pub workspace_id: Option<String>,
     pub name: Option<String>,
     pub desc: Option<String>,
+    pub is_trash: Option<bool>,
 }
 
 impl AppTableChangeset {
@@ -93,6 +96,7 @@ impl AppTableChangeset {
             workspace_id: params.workspace_id,
             name: params.name,
             desc: params.desc,
+            is_trash: params.is_trash,
         }
     }
 }

+ 22 - 2
rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs

@@ -22,19 +22,39 @@ impl ViewTableSql {
         Ok(())
     }
 
-    pub(crate) fn read_view(&self, view_id: &str) -> Result<ViewTable, WorkspaceError> {
+    pub(crate) fn read_view(
+        &self,
+        view_id: &str,
+        is_trash: bool,
+    ) -> Result<ViewTable, WorkspaceError> {
         let view_table = dsl::view_table
             .filter(view_table::id.eq(view_id))
+            .filter(view_table::is_trash.eq(is_trash))
             .first::<ViewTable>(&*(self.database.db_connection()?))?;
 
         Ok(view_table)
     }
 
+    pub(crate) fn read_views_belong_to(
+        &self,
+        belong_to_id: &str,
+    ) -> Result<Vec<ViewTable>, WorkspaceError> {
+        let view_tables = dsl::view_table
+            .filter(view_table::belong_to_id.eq(belong_to_id))
+            .load::<ViewTable>(&*(self.database.db_connection()?))?;
+
+        Ok(view_tables)
+    }
+
     pub(crate) fn update_view(&self, changeset: ViewTableChangeset) -> Result<(), WorkspaceError> {
         let conn = self.database.db_connection()?;
         diesel_update_table!(view_table, changeset, conn);
         Ok(())
     }
 
-    pub fn delete_view(&self, _view_id: &str) -> Result<(), WorkspaceError> { unimplemented!() }
+    pub fn delete_view(&self, view_id: &str) -> Result<(), WorkspaceError> {
+        let conn = self.database.db_connection()?;
+        diesel_delete_table!(view_table, view_id, conn);
+        Ok(())
+    }
 }

+ 4 - 0
rust-lib/flowy-workspace/src/sql_tables/view/view_table.rs

@@ -20,6 +20,7 @@ pub(crate) struct ViewTable {
     pub thumbnail: String,
     pub view_type: ViewTableType,
     pub version: i64,
+    pub is_trash: bool,
 }
 
 impl ViewTable {
@@ -36,6 +37,7 @@ impl ViewTable {
             thumbnail: params.thumbnail,
             view_type: params.view_type,
             version: 0,
+            is_trash: false,
         }
     }
 }
@@ -65,6 +67,7 @@ pub struct ViewTableChangeset {
     pub desc: Option<String>,
     pub thumbnail: Option<String>,
     pub modified_time: i64,
+    pub is_trash: Option<bool>,
 }
 
 impl ViewTableChangeset {
@@ -75,6 +78,7 @@ impl ViewTableChangeset {
             desc: params.desc,
             thumbnail: params.thumbnail,
             modified_time: timestamp(),
+            is_trash: params.is_trash,
         }
     }
 }

+ 4 - 2
rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_sql.rs

@@ -41,8 +41,10 @@ impl WorkspaceSql {
         Ok(())
     }
 
-    pub fn delete_workspace(&self, _workspace_id: &str) -> Result<(), WorkspaceError> {
-        unimplemented!()
+    pub fn delete_workspace(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
+        let conn = self.database.db_connection()?;
+        diesel_delete_table!(workspace_table, workspace_id, conn);
+        Ok(())
     }
 
     pub(crate) fn read_apps_belong_to_workspace(

+ 51 - 20
rust-lib/flowy-workspace/tests/event/app_test.rs

@@ -1,30 +1,36 @@
 use crate::helper::*;
 
-use flowy_workspace::entities::{app::QueryAppRequest, view::*};
+use flowy_workspace::entities::{
+    app::{QueryAppRequest, UpdateAppParams, UpdateAppRequest},
+    view::*,
+};
 
 #[test]
 fn app_create_success() {
-    let workspace = create_workspace("Workspace", "");
-    let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
+    let app = create_app("App A", "AppFlowy Github Project");
     dbg!(&app);
 }
 
+#[test]
+#[should_panic]
+fn app_delete_success() {
+    let app = create_app("App A", "AppFlowy Github Project");
+    delete_app(&app.id);
+    let query = QueryAppRequest::new(&app.id);
+    let _ = read_app(query);
+}
+
 #[test]
 fn app_create_and_then_get_success() {
-    let workspace = create_workspace("Workspace", "");
-    let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
-    let request = QueryAppRequest {
-        app_id: app.id.clone(),
-        read_views: false,
-    };
-    let app_from_db = get_app(request);
+    let app = create_app("App A", "AppFlowy Github Project");
+    let query = QueryAppRequest::new(&app.id);
+    let app_from_db = read_app(query);
     assert_eq!(app_from_db, app);
 }
 
 #[test]
 fn app_create_with_view_and_then_get_success() {
-    let workspace = create_workspace("Workspace", "");
-    let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
+    let app = create_app("App A", "AppFlowy Github Project");
     let request_a = CreateViewRequest {
         belong_to_id: app.id.clone(),
         name: "View A".to_string(),
@@ -41,17 +47,42 @@ fn app_create_with_view_and_then_get_success() {
         view_type: ViewType::Doc,
     };
 
-    let view_a = create_view(request_a);
-    let view_b = create_view(request_b);
+    let view_a = create_view_with_request(request_a);
+    let view_b = create_view_with_request(request_b);
 
-    let query = QueryAppRequest {
-        app_id: app.id.clone(),
-        read_views: true,
-    };
-    let view_from_db = get_app(query);
+    let query = QueryAppRequest::new(&app.id).set_read_views(true);
+    let view_from_db = read_app(query);
 
     assert_eq!(view_from_db.views[0], view_a);
     assert_eq!(view_from_db.views[1], view_b);
 }
 
-// TODO 1) test update app 2) delete app
+#[test]
+fn app_update_with_trash_flag_and_read_with_trash_flag_success() {
+    let app_id = create_app_with_trash_flag();
+    let query = QueryAppRequest::new(&app_id).set_is_trash(true);
+    let _ = read_app(query);
+}
+
+#[test]
+#[should_panic]
+fn app_update_with_trash_flag_and_read_without_trash_flag_fail() {
+    let app_id = create_app_with_trash_flag();
+    let query = QueryAppRequest::new(&app_id);
+    let _ = read_app(query);
+}
+
+pub fn create_app_with_trash_flag() -> String {
+    let app = create_app("App A", "AppFlowy Github Project");
+    let request = UpdateAppRequest {
+        app_id: app.id.clone(),
+        workspace_id: None,
+        name: None,
+        desc: None,
+        color_style: None,
+        is_trash: Some(true),
+    };
+    update_app(request);
+
+    app.id
+}

+ 60 - 12
rust-lib/flowy-workspace/tests/event/helper.rs

@@ -26,9 +26,21 @@ pub fn create_workspace(name: &str, desc: &str) -> Workspace {
     workspace
 }
 
-pub fn create_app(name: &str, desc: &str, workspace_id: &str) -> App {
+pub fn read_workspace(request: QueryWorkspaceRequest) -> Workspace {
+    let workspace = SingleUserTestBuilder::new()
+        .event(ReadWorkspace)
+        .request(request)
+        .sync_send()
+        .parse::<Workspace>();
+
+    workspace
+}
+
+pub fn create_app(name: &str, desc: &str) -> App {
+    let workspace = create_workspace("Workspace", "");
+
     let create_app_request = CreateAppRequest {
-        workspace_id: workspace_id.to_string(),
+        workspace_id: workspace.id,
         name: name.to_string(),
         desc: desc.to_string(),
         color_style: Default::default(),
@@ -42,19 +54,27 @@ pub fn create_app(name: &str, desc: &str, workspace_id: &str) -> App {
     app
 }
 
-pub fn get_workspace(request: QueryWorkspaceRequest) -> Workspace {
-    let workspace = SingleUserTestBuilder::new()
-        .event(GetWorkspace)
-        .request(request)
-        .sync_send()
-        .parse::<Workspace>();
+pub fn delete_app(app_id: &str) {
+    let delete_app_request = DeleteAppRequest {
+        app_id: app_id.to_string(),
+    };
 
-    workspace
+    SingleUserTestBuilder::new()
+        .event(DeleteApp)
+        .request(delete_app_request)
+        .sync_send();
 }
 
-pub fn get_app(request: QueryAppRequest) -> App {
+pub fn update_app(request: UpdateAppRequest) {
+    SingleUserTestBuilder::new()
+        .event(UpdateApp)
+        .request(request)
+        .sync_send();
+}
+
+pub fn read_app(request: QueryAppRequest) -> App {
     let app = SingleUserTestBuilder::new()
-        .event(GetApp)
+        .event(ReadApp)
         .request(request)
         .sync_send()
         .parse::<App>();
@@ -62,7 +82,7 @@ pub fn get_app(request: QueryAppRequest) -> App {
     app
 }
 
-pub fn create_view(request: CreateViewRequest) -> View {
+pub fn create_view_with_request(request: CreateViewRequest) -> View {
     let view = SingleUserTestBuilder::new()
         .event(CreateView)
         .request(request)
@@ -71,3 +91,31 @@ pub fn create_view(request: CreateViewRequest) -> View {
 
     view
 }
+
+pub fn create_view() -> View {
+    let app = create_app("App A", "AppFlowy Github Project");
+    let request = CreateViewRequest {
+        belong_to_id: app.id.clone(),
+        name: "View A".to_string(),
+        desc: "".to_string(),
+        thumbnail: None,
+        view_type: ViewType::Doc,
+    };
+
+    create_view_with_request(request)
+}
+
+pub fn update_view(request: UpdateViewRequest) {
+    SingleUserTestBuilder::new()
+        .event(UpdateView)
+        .request(request)
+        .sync_send();
+}
+
+pub fn read_view(request: QueryViewRequest) -> View {
+    SingleUserTestBuilder::new()
+        .event(ReadView)
+        .request(request)
+        .sync_send()
+        .parse::<View>()
+}

+ 35 - 0
rust-lib/flowy-workspace/tests/event/view_test.rs

@@ -0,0 +1,35 @@
+use crate::helper::*;
+
+use flowy_workspace::entities::view::*;
+
+#[test]
+fn view_create_success() { let _ = create_view(); }
+
+#[test]
+fn view_update_with_trash_flag_and_read_with_trash_flag_success() {
+    let view_id = create_view_with_trash_flag();
+    let query = QueryViewRequest::new(&view_id).set_is_trash(true);
+    let _ = read_view(query);
+}
+
+#[test]
+#[should_panic]
+fn view_update_with_trash_flag_and_read_without_trash_flag_fail() {
+    let view_id = create_view_with_trash_flag();
+    let query = QueryViewRequest::new(&view_id);
+    let _ = read_view(query);
+}
+
+pub fn create_view_with_trash_flag() -> String {
+    let view = create_view();
+    let request = UpdateViewRequest {
+        view_id: view.id.clone(),
+        name: None,
+        desc: None,
+        thumbnail: None,
+        is_trash: Some(true),
+    };
+    update_view(request);
+
+    view.id
+}

+ 5 - 7
rust-lib/flowy-workspace/tests/event/workspace_test.rs

@@ -11,7 +11,7 @@ fn workspace_create_success() { let _ = create_workspace("First workspace", "");
 #[test]
 fn workspace_get_success() {
     let workspace = SingleUserTestBuilder::new()
-        .event(GetCurWorkspace)
+        .event(ReadCurWorkspace)
         .sync_send()
         .parse::<Workspace>();
 
@@ -39,21 +39,19 @@ fn workspace_create_and_then_get_workspace_success() {
         read_apps: false,
     };
 
-    let workspace_from_db = get_workspace(request);
+    let workspace_from_db = read_workspace(request);
     assert_eq!(workspace.name, workspace_from_db.name);
 }
 
 #[test]
 fn workspace_create_with_apps_success() {
-    let workspace = create_workspace("Workspace B", "");
-    let app = create_app("App A", "", &workspace.id);
-
+    let app = create_app("App A", "");
     let query_workspace_request = QueryWorkspaceRequest {
-        workspace_id: workspace.id.clone(),
+        workspace_id: app.workspace_id.clone(),
         read_apps: true,
     };
 
-    let workspace_from_db = get_workspace(query_workspace_request);
+    let workspace_from_db = read_workspace(query_workspace_request);
     assert_eq!(&app, workspace_from_db.apps.first_or_crash());
 }