Kaynağa Gözat

Merge pull request #1121 from AppFlowy-IO/fix/black_page_after_delete_doc

chore: open next page when current page get deleted
Nathan.fooo 2 yıl önce
ebeveyn
işleme
f84e0548a8
25 değiştirilmiş dosya ile 312 ekleme ve 177 silme
  1. 3 8
      frontend/app_flowy/lib/plugins/blank/blank.dart
  2. 20 8
      frontend/app_flowy/lib/plugins/board/board.dart
  3. 4 1
      frontend/app_flowy/lib/plugins/board/presentation/board_page.dart
  4. 23 36
      frontend/app_flowy/lib/plugins/doc/document.dart
  5. 8 8
      frontend/app_flowy/lib/plugins/doc/document_page.dart
  6. 20 8
      frontend/app_flowy/lib/plugins/grid/grid.dart
  7. 6 1
      frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart
  8. 3 1
      frontend/app_flowy/lib/plugins/trash/trash.dart
  9. 44 0
      frontend/app_flowy/lib/plugins/util.dart
  10. 1 1
      frontend/app_flowy/lib/startup/deps_resolver.dart
  11. 23 23
      frontend/app_flowy/lib/startup/plugin/plugin.dart
  12. 1 6
      frontend/app_flowy/lib/workspace/application/app/app_service.dart
  13. 14 0
      frontend/app_flowy/lib/workspace/application/home/home_service.dart
  14. 11 6
      frontend/app_flowy/lib/workspace/application/menu/menu_view_section_bloc.dart
  15. 33 8
      frontend/app_flowy/lib/workspace/application/view/view_listener.dart
  16. 6 3
      frontend/app_flowy/lib/workspace/application/workspace/workspace_service.dart
  17. 44 3
      frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart
  18. 23 14
      frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart
  19. 10 3
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart
  20. 1 0
      frontend/rust-lib/flowy-folder/src/dart_notification.rs
  21. 0 2
      frontend/rust-lib/flowy-folder/src/manager.rs
  22. 12 6
      frontend/rust-lib/flowy-folder/src/services/view/controller.rs
  23. 2 2
      frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs
  24. 0 11
      frontend/rust-lib/flowy-grid/src/manager.rs
  25. 0 18
      frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs

+ 3 - 8
frontend/app_flowy/lib/plugins/blank/blank.dart

@@ -9,7 +9,7 @@ import 'package:app_flowy/startup/plugin/plugin.dart';
 class BlankPluginBuilder extends PluginBuilder {
 class BlankPluginBuilder extends PluginBuilder {
   @override
   @override
   Plugin build(dynamic data) {
   Plugin build(dynamic data) {
-    return BlankPagePlugin(pluginType: pluginType);
+    return BlankPagePlugin();
   }
   }
 
 
   @override
   @override
@@ -25,11 +25,6 @@ class BlankPluginConfig implements PluginConfig {
 }
 }
 
 
 class BlankPagePlugin extends Plugin {
 class BlankPagePlugin extends Plugin {
-  final PluginType _pluginType;
-  BlankPagePlugin({
-    required PluginType pluginType,
-  }) : _pluginType = pluginType;
-
   @override
   @override
   PluginDisplay get display => BlankPagePluginDisplay();
   PluginDisplay get display => BlankPagePluginDisplay();
 
 
@@ -37,7 +32,7 @@ class BlankPagePlugin extends Plugin {
   PluginId get id => "BlankStack";
   PluginId get id => "BlankStack";
 
 
   @override
   @override
-  PluginType get ty => _pluginType;
+  PluginType get ty => PluginType.blank;
 }
 }
 
 
 class BlankPagePluginDisplay extends PluginDisplay with NavigationItem {
 class BlankPagePluginDisplay extends PluginDisplay with NavigationItem {
@@ -46,7 +41,7 @@ class BlankPagePluginDisplay extends PluginDisplay with NavigationItem {
       FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12);
       FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12);
 
 
   @override
   @override
-  Widget buildWidget() => const BlankPage();
+  Widget buildWidget(PluginContext context) => const BlankPage();
 
 
   @override
   @override
   List<NavigationItem> get navigationItems => [this];
   List<NavigationItem> get navigationItems => [this];

+ 20 - 8
frontend/app_flowy/lib/plugins/board/board.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/plugins/util.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
 import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
@@ -35,34 +36,45 @@ class BoardPluginConfig implements PluginConfig {
 }
 }
 
 
 class BoardPlugin extends Plugin {
 class BoardPlugin extends Plugin {
-  final ViewPB _view;
+  @override
+  final ViewPluginNotifier notifier;
   final PluginType _pluginType;
   final PluginType _pluginType;
 
 
   BoardPlugin({
   BoardPlugin({
     required ViewPB view,
     required ViewPB view,
     required PluginType pluginType,
     required PluginType pluginType,
   })  : _pluginType = pluginType,
   })  : _pluginType = pluginType,
-        _view = view;
+        notifier = ViewPluginNotifier(view: view);
 
 
   @override
   @override
-  PluginDisplay get display => GridPluginDisplay(view: _view);
+  PluginDisplay get display => GridPluginDisplay(notifier: notifier);
 
 
   @override
   @override
-  PluginId get id => _view.id;
+  PluginId get id => notifier.view.id;
 
 
   @override
   @override
   PluginType get ty => _pluginType;
   PluginType get ty => _pluginType;
 }
 }
 
 
 class GridPluginDisplay extends PluginDisplay {
 class GridPluginDisplay extends PluginDisplay {
-  final ViewPB _view;
-  GridPluginDisplay({required ViewPB view, Key? key}) : _view = view;
+  final ViewPluginNotifier notifier;
+  GridPluginDisplay({required this.notifier, Key? key});
+
+  ViewPB get view => notifier.view;
 
 
   @override
   @override
-  Widget get leftBarItem => ViewLeftBarItem(view: _view);
+  Widget get leftBarItem => ViewLeftBarItem(view: view);
 
 
   @override
   @override
-  Widget buildWidget() => BoardPage(view: _view);
+  Widget buildWidget(PluginContext context) {
+    notifier.isDeleted.addListener(() {
+      if (notifier.isDeleted.value) {
+        context.onDeleted(view);
+      }
+    });
+
+    return BoardPage(key: ValueKey(view.id), view: view);
+  }
 
 
   @override
   @override
   List<NavigationItem> get navigationItems => [this];
   List<NavigationItem> get navigationItems => [this];

+ 4 - 1
frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

@@ -31,7 +31,10 @@ import 'toolbar/board_toolbar.dart';
 
 
 class BoardPage extends StatelessWidget {
 class BoardPage extends StatelessWidget {
   final ViewPB view;
   final ViewPB view;
-  BoardPage({required this.view, Key? key}) : super(key: ValueKey(view.id));
+  BoardPage({
+    required this.view,
+    Key? key,
+  }) : super(key: ValueKey(view.id));
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {

+ 23 - 36
frontend/app_flowy/lib/plugins/doc/document.dart

@@ -1,10 +1,10 @@
 library document_plugin;
 library document_plugin;
 
 
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
+import 'package:app_flowy/plugins/util.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/workspace/application/appearance.dart';
-import 'package:app_flowy/workspace/application/view/view_listener.dart';
 import 'package:app_flowy/plugins/doc/application/share_bloc.dart';
 import 'package:app_flowy/plugins/doc/application/share_bloc.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/toast.dart';
 import 'package:app_flowy/workspace/presentation/home/toast.dart';
@@ -14,7 +14,6 @@ import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
 import 'package:clipboard/clipboard.dart';
 import 'package:clipboard/clipboard.dart';
 import 'package:dartz/dartz.dart' as dartz;
 import 'package:dartz/dartz.dart' as dartz;
 import 'package:easy_localization/easy_localization.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
@@ -48,63 +47,51 @@ class DocumentPluginBuilder extends PluginBuilder {
   ViewDataTypePB get dataType => ViewDataTypePB.Text;
   ViewDataTypePB get dataType => ViewDataTypePB.Text;
 }
 }
 
 
-class DocumentPlugin implements Plugin {
-  late ViewPB _view;
-  ViewListener? _listener;
+class DocumentPlugin extends Plugin<int> {
   late PluginType _pluginType;
   late PluginType _pluginType;
 
 
-  DocumentPlugin(
-      {required PluginType pluginType, required ViewPB view, Key? key})
-      : _view = view {
-    _pluginType = pluginType;
-    _listener = getIt<ViewListener>(param1: view);
-    _listener?.start(onViewUpdated: (result) {
-      result.fold(
-        (newView) {
-          _view = newView;
-          display.notifier!.value = _view.hashCode;
-        },
-        (error) {},
-      );
-    });
-  }
-
   @override
   @override
-  void dispose() {
-    _listener?.stop();
-    _listener = null;
+  final ViewPluginNotifier notifier;
+
+  DocumentPlugin({
+    required PluginType pluginType,
+    required ViewPB view,
+    Key? key,
+  }) : notifier = ViewPluginNotifier(view: view) {
+    _pluginType = pluginType;
   }
   }
 
 
   @override
   @override
-  PluginDisplay<int> get display => DocumentPluginDisplay(view: _view);
+  PluginDisplay get display => DocumentPluginDisplay(notifier: notifier);
 
 
   @override
   @override
   PluginType get ty => _pluginType;
   PluginType get ty => _pluginType;
 
 
   @override
   @override
-  PluginId get id => _view.id;
+  PluginId get id => notifier.view.id;
 }
 }
 
 
-class DocumentPluginDisplay extends PluginDisplay<int> with NavigationItem {
-  final PublishNotifier<int> _displayNotifier = PublishNotifier<int>();
-  final ViewPB _view;
+class DocumentPluginDisplay extends PluginDisplay with NavigationItem {
+  final ViewPluginNotifier notifier;
+  ViewPB get view => notifier.view;
 
 
-  DocumentPluginDisplay({required ViewPB view, Key? key}) : _view = view;
+  DocumentPluginDisplay({required this.notifier, Key? key});
 
 
   @override
   @override
-  Widget buildWidget() => DocumentPage(view: _view, key: ValueKey(_view.id));
+  Widget buildWidget(PluginContext context) => DocumentPage(
+        view: view,
+        onDeleted: () => context.onDeleted(view),
+        key: ValueKey(view.id),
+      );
 
 
   @override
   @override
-  Widget get leftBarItem => ViewLeftBarItem(view: _view);
+  Widget get leftBarItem => ViewLeftBarItem(view: view);
 
 
   @override
   @override
-  Widget? get rightBarItem => DocumentShareButton(view: _view);
+  Widget? get rightBarItem => DocumentShareButton(view: view);
 
 
   @override
   @override
   List<NavigationItem> get navigationItems => [this];
   List<NavigationItem> get navigationItems => [this];
-
-  @override
-  PublishNotifier<int>? get notifier => _displayNotifier;
 }
 }
 
 
 class DocumentShareButton extends StatelessWidget {
 class DocumentShareButton extends StatelessWidget {

+ 8 - 8
frontend/app_flowy/lib/plugins/doc/document_page.dart

@@ -14,9 +14,14 @@ import 'application/doc_bloc.dart';
 import 'styles.dart';
 import 'styles.dart';
 
 
 class DocumentPage extends StatefulWidget {
 class DocumentPage extends StatefulWidget {
+  final VoidCallback onDeleted;
   final ViewPB view;
   final ViewPB view;
 
 
-  DocumentPage({Key? key, required this.view}) : super(key: ValueKey(view.id));
+  DocumentPage({
+    required this.view,
+    required this.onDeleted,
+    Key? key,
+  }) : super(key: ValueKey(view.id));
 
 
   @override
   @override
   State<DocumentPage> createState() => _DocumentPageState();
   State<DocumentPage> createState() => _DocumentPageState();
@@ -49,7 +54,8 @@ class _DocumentPageState extends State<DocumentPage> {
           finish: (result) => result.successOrFail.fold(
           finish: (result) => result.successOrFail.fold(
             (_) {
             (_) {
               if (state.forceClose) {
               if (state.forceClose) {
-                return _renderAppPage();
+                widget.onDeleted();
+                return const SizedBox();
               } else {
               } else {
                 return _renderDocument(context, state);
                 return _renderDocument(context, state);
               }
               }
@@ -134,10 +140,4 @@ class _DocumentPageState extends State<DocumentPage> {
       ),
       ),
     );
     );
   }
   }
-
-  Widget _renderAppPage() {
-    return Container(
-      color: Colors.black,
-    );
-  }
 }
 }

+ 20 - 8
frontend/app_flowy/lib/plugins/grid/grid.dart

@@ -1,4 +1,5 @@
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
+import 'package:app_flowy/plugins/util.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
 import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
@@ -37,34 +38,45 @@ class GridPluginConfig implements PluginConfig {
 }
 }
 
 
 class GridPlugin extends Plugin {
 class GridPlugin extends Plugin {
-  final ViewPB _view;
+  @override
+  final ViewPluginNotifier notifier;
   final PluginType _pluginType;
   final PluginType _pluginType;
 
 
   GridPlugin({
   GridPlugin({
     required ViewPB view,
     required ViewPB view,
     required PluginType pluginType,
     required PluginType pluginType,
   })  : _pluginType = pluginType,
   })  : _pluginType = pluginType,
-        _view = view;
+        notifier = ViewPluginNotifier(view: view);
 
 
   @override
   @override
-  PluginDisplay get display => GridPluginDisplay(view: _view);
+  PluginDisplay get display => GridPluginDisplay(notifier: notifier);
 
 
   @override
   @override
-  PluginId get id => _view.id;
+  PluginId get id => notifier.view.id;
 
 
   @override
   @override
   PluginType get ty => _pluginType;
   PluginType get ty => _pluginType;
 }
 }
 
 
 class GridPluginDisplay extends PluginDisplay {
 class GridPluginDisplay extends PluginDisplay {
-  final ViewPB _view;
-  GridPluginDisplay({required ViewPB view, Key? key}) : _view = view;
+  final ViewPluginNotifier notifier;
+  ViewPB get view => notifier.view;
+
+  GridPluginDisplay({required this.notifier, Key? key});
 
 
   @override
   @override
-  Widget get leftBarItem => ViewLeftBarItem(view: _view);
+  Widget get leftBarItem => ViewLeftBarItem(view: view);
 
 
   @override
   @override
-  Widget buildWidget() => GridPage(view: _view);
+  Widget buildWidget(PluginContext context) {
+    notifier.isDeleted.addListener(() {
+      if (notifier.isDeleted.value) {
+        context.onDeleted(view);
+      }
+    });
+
+    return GridPage(key: ValueKey(view.id), view: view);
+  }
 
 
   @override
   @override
   List<NavigationItem> get navigationItems => [this];
   List<NavigationItem> get navigationItems => [this];

+ 6 - 1
frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart

@@ -29,8 +29,13 @@ import 'widgets/toolbar/grid_toolbar.dart';
 
 
 class GridPage extends StatefulWidget {
 class GridPage extends StatefulWidget {
   final ViewPB view;
   final ViewPB view;
+  final VoidCallback? onDeleted;
 
 
-  GridPage({Key? key, required this.view}) : super(key: ValueKey(view.id));
+  GridPage({
+    required this.view,
+    this.onDeleted,
+    Key? key,
+  }) : super(key: ValueKey(view.id));
 
 
   @override
   @override
   State<GridPage> createState() => _GridPageState();
   State<GridPage> createState() => _GridPageState();

+ 3 - 1
frontend/app_flowy/lib/plugins/trash/trash.dart

@@ -53,7 +53,9 @@ class TrashPluginDisplay extends PluginDisplay {
   Widget? get rightBarItem => null;
   Widget? get rightBarItem => null;
 
 
   @override
   @override
-  Widget buildWidget() => const TrashPage(key: ValueKey('TrashPage'));
+  Widget buildWidget(PluginContext context) => const TrashPage(
+        key: ValueKey('TrashPage'),
+      );
 
 
   @override
   @override
   List<NavigationItem> get navigationItems => [this];
   List<NavigationItem> get navigationItems => [this];

+ 44 - 0
frontend/app_flowy/lib/plugins/util.dart

@@ -0,0 +1,44 @@
+import 'package:app_flowy/startup/plugin/plugin.dart';
+import 'package:app_flowy/workspace/application/view/view_listener.dart';
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
+import 'package:flutter/material.dart';
+
+class ViewPluginNotifier extends PluginNotifier {
+  final ViewListener? _viewListener;
+  ViewPB view;
+
+  @override
+  final ValueNotifier<bool> isDeleted = ValueNotifier(false);
+
+  @override
+  final ValueNotifier<int> isDisplayChanged = ValueNotifier(0);
+
+  ViewPluginNotifier({
+    required this.view,
+  }) : _viewListener = ViewListener(view: view) {
+    _viewListener?.start(onViewUpdated: (result) {
+      result.fold(
+        (updatedView) {
+          view = updatedView;
+          isDisplayChanged.value = updatedView.hashCode;
+        },
+        (err) => Log.error(err),
+      );
+    }, onViewMoveToTrash: (result) {
+      result.fold(
+        (deletedView) {
+          isDeleted.value = true;
+        },
+        (err) => Log.error(err),
+      );
+    });
+  }
+
+  @override
+  void dispose() {
+    isDeleted.dispose();
+    isDisplayChanged.dispose();
+    _viewListener?.stop();
+  }
+}

+ 1 - 1
frontend/app_flowy/lib/startup/deps_resolver.dart

@@ -120,7 +120,7 @@ void _resolveFolderDeps(GetIt getIt) {
   getIt.registerFactoryParam<AppBloc, AppPB, void>(
   getIt.registerFactoryParam<AppBloc, AppPB, void>(
     (app, _) => AppBloc(
     (app, _) => AppBloc(
       app: app,
       app: app,
-      appService: AppService(appId: app.id),
+      appService: AppService(),
       appListener: AppListener(appId: app.id),
       appListener: AppListener(appId: app.id),
     ),
     ),
   );
   );

+ 23 - 23
frontend/app_flowy/lib/startup/plugin/plugin.dart

@@ -3,7 +3,6 @@ library flowy_plugin;
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
-import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter/widgets.dart';
 
 
@@ -17,33 +16,29 @@ enum PluginType {
   board,
   board,
 }
 }
 
 
-// extension FlowyDefaultPluginExt on DefaultPlugin {
-//   int type() {
-//     switch (this) {
-//       case DefaultPlugin.editor:
-//         return 0;
-//       case DefaultPlugin.blank:
-//         return 1;
-//       case DefaultPlugin.trash:
-//         return 2;
-//       case DefaultPlugin.grid:
-//         return 3;
-//       case DefaultPlugin.board:
-//         return 4;
-//     }
-//   }
-// }
-
-// typedef PluginType = int;
 typedef PluginId = String;
 typedef PluginId = String;
 
 
-abstract class Plugin {
+abstract class Plugin<T> {
   PluginId get id;
   PluginId get id;
 
 
   PluginDisplay get display;
   PluginDisplay get display;
 
 
+  PluginNotifier? get notifier => null;
+
   PluginType get ty;
   PluginType get ty;
 
 
+  void dispose() {
+    notifier?.dispose();
+  }
+}
+
+abstract class PluginNotifier {
+  /// Notify if the plugin get deleted
+  ValueNotifier<bool> get isDeleted;
+
+  /// Notify if the [PluginDisplay]'s content was changed
+  ValueNotifier<int> get isDisplayChanged;
+
   void dispose() {}
   void dispose() {}
 }
 }
 
 
@@ -64,12 +59,17 @@ abstract class PluginConfig {
   bool get creatable => true;
   bool get creatable => true;
 }
 }
 
 
-abstract class PluginDisplay<T> with NavigationItem {
+abstract class PluginDisplay with NavigationItem {
   List<NavigationItem> get navigationItems;
   List<NavigationItem> get navigationItems;
 
 
-  PublishNotifier<T>? get notifier => null;
+  Widget buildWidget(PluginContext context);
+}
+
+class PluginContext {
+  // calls when widget of the plugin get deleted
+  final Function(ViewPB) onDeleted;
 
 
-  Widget buildWidget();
+  PluginContext({required this.onDeleted});
 }
 }
 
 
 void registerPlugin({required PluginBuilder builder, PluginConfig? config}) {
 void registerPlugin({required PluginBuilder builder, PluginConfig? config}) {

+ 1 - 6
frontend/app_flowy/lib/workspace/application/app/app_service.dart

@@ -9,12 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 
 
 class AppService {
 class AppService {
-  final String appId;
-  AppService({
-    required this.appId,
-  });
-
-  Future<Either<AppPB, FlowyError>> getAppDesc({required String appId}) {
+  Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
     final payload = AppIdPB.create()..value = appId;
     final payload = AppIdPB.create()..value = appId;
 
 
     return FolderEventReadApp(payload).send();
     return FolderEventReadApp(payload).send();

+ 14 - 0
frontend/app_flowy/lib/workspace/application/home/home_service.dart

@@ -0,0 +1,14 @@
+import 'dart:async';
+
+import 'package:dartz/dartz.dart';
+import 'package:flowy_sdk/dispatch/dispatch.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
+
+class HomeService {
+  Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
+    final payload = AppIdPB.create()..value = appId;
+
+    return FolderEventReadApp(payload).send();
+  }
+}

+ 11 - 6
frontend/app_flowy/lib/workspace/application/menu/menu_view_section_bloc.dart

@@ -17,7 +17,7 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
 
 
   ViewSectionBloc({
   ViewSectionBloc({
     required AppViewDataContext appViewData,
     required AppViewDataContext appViewData,
-  })  : _appService = AppService(appId: appViewData.appId),
+  })  : _appService = AppService(),
         _appViewData = appViewData,
         _appViewData = appViewData,
         super(ViewSectionState.initial(appViewData)) {
         super(ViewSectionState.initial(appViewData)) {
     on<ViewSectionEvent>((event, emit) async {
     on<ViewSectionEvent>((event, emit) async {
@@ -59,7 +59,8 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
     }
     }
   }
   }
 
 
-  Future<void> _moveView(_MoveView value, Emitter<ViewSectionState> emit) async {
+  Future<void> _moveView(
+      _MoveView value, Emitter<ViewSectionState> emit) async {
     if (value.fromIndex < state.views.length) {
     if (value.fromIndex < state.views.length) {
       final viewId = state.views[value.fromIndex].id;
       final viewId = state.views[value.fromIndex].id;
       final views = List<ViewPB>.from(state.views);
       final views = List<ViewPB>.from(state.views);
@@ -92,9 +93,12 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
 @freezed
 @freezed
 class ViewSectionEvent with _$ViewSectionEvent {
 class ViewSectionEvent with _$ViewSectionEvent {
   const factory ViewSectionEvent.initial() = _Initial;
   const factory ViewSectionEvent.initial() = _Initial;
-  const factory ViewSectionEvent.setSelectedView(ViewPB? view) = _SetSelectedView;
-  const factory ViewSectionEvent.moveView(int fromIndex, int toIndex) = _MoveView;
-  const factory ViewSectionEvent.didReceiveViewUpdated(List<ViewPB> views) = _DidReceiveViewUpdated;
+  const factory ViewSectionEvent.setSelectedView(ViewPB? view) =
+      _SetSelectedView;
+  const factory ViewSectionEvent.moveView(int fromIndex, int toIndex) =
+      _MoveView;
+  const factory ViewSectionEvent.didReceiveViewUpdated(List<ViewPB> views) =
+      _DidReceiveViewUpdated;
 }
 }
 
 
 @freezed
 @freezed
@@ -104,7 +108,8 @@ class ViewSectionState with _$ViewSectionState {
     ViewPB? selectedView,
     ViewPB? selectedView,
   }) = _ViewSectionState;
   }) = _ViewSectionState;
 
 
-  factory ViewSectionState.initial(AppViewDataContext appViewData) => ViewSectionState(
+  factory ViewSectionState.initial(AppViewDataContext appViewData) =>
+      ViewSectionState(
         views: appViewData.views,
         views: appViewData.views,
         selectedView: appViewData.selectedView,
         selectedView: appViewData.selectedView,
       );
       );

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

@@ -9,15 +9,21 @@ import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
 import 'package:flowy_sdk/rust_stream.dart';
 import 'package:flowy_sdk/rust_stream.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_infra/notifier.dart';
 
 
+// Delete the view from trash, which means the view was deleted permanently
 typedef DeleteViewNotifyValue = Either<ViewPB, FlowyError>;
 typedef DeleteViewNotifyValue = Either<ViewPB, FlowyError>;
+// The view get updated
 typedef UpdateViewNotifiedValue = Either<ViewPB, FlowyError>;
 typedef UpdateViewNotifiedValue = Either<ViewPB, FlowyError>;
+// Restore the view from trash
 typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
 typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
+// Move the view to trash
+typedef MoveToTrashNotifiedValue = Either<ViewIdPB, FlowyError>;
 
 
 class ViewListener {
 class ViewListener {
   StreamSubscription<SubscribeObject>? _subscription;
   StreamSubscription<SubscribeObject>? _subscription;
-  final PublishNotifier<UpdateViewNotifiedValue> _updatedViewNotifier = PublishNotifier();
-  final PublishNotifier<DeleteViewNotifyValue> _deletedNotifier = PublishNotifier();
-  final PublishNotifier<RestoreViewNotifiedValue> _restoredNotifier = PublishNotifier();
+  final _updatedViewNotifier = PublishNotifier<UpdateViewNotifiedValue>();
+  final _deletedNotifier = PublishNotifier<DeleteViewNotifyValue>();
+  final _restoredNotifier = PublishNotifier<RestoreViewNotifiedValue>();
+  final _moveToTrashNotifier = PublishNotifier<MoveToTrashNotifiedValue>();
   FolderNotificationParser? _parser;
   FolderNotificationParser? _parser;
   ViewPB view;
   ViewPB view;
 
 
@@ -29,6 +35,7 @@ class ViewListener {
     void Function(UpdateViewNotifiedValue)? onViewUpdated,
     void Function(UpdateViewNotifiedValue)? onViewUpdated,
     void Function(DeleteViewNotifyValue)? onViewDeleted,
     void Function(DeleteViewNotifyValue)? onViewDeleted,
     void Function(RestoreViewNotifiedValue)? onViewRestored,
     void Function(RestoreViewNotifiedValue)? onViewRestored,
+    void Function(MoveToTrashNotifiedValue)? onViewMoveToTrash,
   }) {
   }) {
     if (onViewUpdated != null) {
     if (onViewUpdated != null) {
       _updatedViewNotifier.addListener(() {
       _updatedViewNotifier.addListener(() {
@@ -48,6 +55,12 @@ class ViewListener {
       });
       });
     }
     }
 
 
+    if (onViewMoveToTrash != null) {
+      _moveToTrashNotifier.addListener(() {
+        onViewMoveToTrash(_moveToTrashNotifier.currentValue!);
+      });
+    }
+
     _parser = FolderNotificationParser(
     _parser = FolderNotificationParser(
       id: view.id,
       id: view.id,
       callback: (ty, result) {
       callback: (ty, result) {
@@ -55,29 +68,41 @@ class ViewListener {
       },
       },
     );
     );
 
 
-    _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
+    _subscription =
+        RustStreamReceiver.listen((observable) => _parser?.parse(observable));
   }
   }
 
 
-  void _handleObservableType(FolderNotification ty, Either<Uint8List, FlowyError> result) {
+  void _handleObservableType(
+      FolderNotification ty, Either<Uint8List, FlowyError> result) {
     switch (ty) {
     switch (ty) {
       case FolderNotification.ViewUpdated:
       case FolderNotification.ViewUpdated:
         result.fold(
         result.fold(
-          (payload) => _updatedViewNotifier.value = left(ViewPB.fromBuffer(payload)),
+          (payload) =>
+              _updatedViewNotifier.value = left(ViewPB.fromBuffer(payload)),
           (error) => _updatedViewNotifier.value = right(error),
           (error) => _updatedViewNotifier.value = right(error),
         );
         );
         break;
         break;
       case FolderNotification.ViewDeleted:
       case FolderNotification.ViewDeleted:
         result.fold(
         result.fold(
-          (payload) => _deletedNotifier.value = left(ViewPB.fromBuffer(payload)),
+          (payload) =>
+              _deletedNotifier.value = left(ViewPB.fromBuffer(payload)),
           (error) => _deletedNotifier.value = right(error),
           (error) => _deletedNotifier.value = right(error),
         );
         );
         break;
         break;
       case FolderNotification.ViewRestored:
       case FolderNotification.ViewRestored:
         result.fold(
         result.fold(
-          (payload) => _restoredNotifier.value = left(ViewPB.fromBuffer(payload)),
+          (payload) =>
+              _restoredNotifier.value = left(ViewPB.fromBuffer(payload)),
           (error) => _restoredNotifier.value = right(error),
           (error) => _restoredNotifier.value = right(error),
         );
         );
         break;
         break;
+      case FolderNotification.ViewMoveToTrash:
+        result.fold(
+          (payload) =>
+              _moveToTrashNotifier.value = left(ViewIdPB.fromBuffer(payload)),
+          (error) => _moveToTrashNotifier.value = right(error),
+        );
+        break;
       default:
       default:
         break;
         break;
     }
     }

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

@@ -5,7 +5,8 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart' show MoveFolderItemPayloadPB, MoveFolderItemType;
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'
+    show MoveFolderItemPayloadPB, MoveFolderItemType;
 import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
 
 
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
@@ -15,7 +16,8 @@ class WorkspaceService {
   WorkspaceService({
   WorkspaceService({
     required this.workspaceId,
     required this.workspaceId,
   });
   });
-  Future<Either<AppPB, FlowyError>> createApp({required String name, required String desc}) {
+  Future<Either<AppPB, FlowyError>> createApp(
+      {required String name, required String desc}) {
     final payload = CreateAppPayloadPB.create()
     final payload = CreateAppPayloadPB.create()
       ..name = name
       ..name = name
       ..workspaceId = workspaceId
       ..workspaceId = workspaceId
@@ -31,7 +33,8 @@ class WorkspaceService {
           assert(workspaces.items.length == 1);
           assert(workspaces.items.length == 1);
 
 
           if (workspaces.items.isEmpty) {
           if (workspaces.items.isEmpty) {
-            return right(FlowyError.create()..msg = LocaleKeys.workspace_notFoundError.tr());
+            return right(FlowyError.create()
+              ..msg = LocaleKeys.workspace_notFoundError.tr());
           } else {
           } else {
             return left(workspaces.items[0]);
             return left(workspaces.items[0]);
           }
           }

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

@@ -1,5 +1,7 @@
+import 'package:app_flowy/plugins/blank/blank.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/workspace/application/home/home_bloc.dart';
 import 'package:app_flowy/workspace/application/home/home_bloc.dart';
+import 'package:app_flowy/workspace/application/home/home_service.dart';
 
 
 import 'package:app_flowy/workspace/presentation/home/hotkeys.dart';
 import 'package:app_flowy/workspace/presentation/home/hotkeys.dart';
 import 'package:app_flowy/workspace/application/view/view_ext.dart';
 import 'package:app_flowy/workspace/application/view/view_ext.dart';
@@ -78,7 +80,7 @@ class _HomeScreenState extends State<HomeScreen> {
               return FlowyContainer(
               return FlowyContainer(
                 Theme.of(context).colorScheme.surface,
                 Theme.of(context).colorScheme.surface,
                 // Colors.white,
                 // Colors.white,
-                child: _buildBody(state),
+                child: _buildBody(context, state),
               );
               );
             },
             },
           ),
           ),
@@ -87,12 +89,16 @@ class _HomeScreenState extends State<HomeScreen> {
     );
     );
   }
   }
 
 
-  Widget _buildBody(HomeState state) {
+  Widget _buildBody(BuildContext context, HomeState state) {
     return LayoutBuilder(
     return LayoutBuilder(
       builder: (BuildContext context, BoxConstraints constraints) {
       builder: (BuildContext context, BoxConstraints constraints) {
         final layout = HomeLayout(context, constraints, state.forceCollapse);
         final layout = HomeLayout(context, constraints, state.forceCollapse);
         final homeStack = HomeStack(
         final homeStack = HomeStack(
           layout: layout,
           layout: layout,
+          delegate: HomeScreenStackAdaptor(
+            buildContext: context,
+            homeState: state,
+          ),
         );
         );
         final menu = _buildHomeMenu(
         final menu = _buildHomeMenu(
           layout: layout,
           layout: layout,
@@ -132,7 +138,7 @@ class _HomeScreenState extends State<HomeScreen> {
       getIt<HomeStackManager>().setPlugin(plugin);
       getIt<HomeStackManager>().setPlugin(plugin);
     }
     }
 
 
-    HomeMenu homeMenu = HomeMenu(
+    final homeMenu = HomeMenu(
       user: widget.user,
       user: widget.user,
       workspaceSetting: workspaceSetting,
       workspaceSetting: workspaceSetting,
       collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
       collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
@@ -244,3 +250,38 @@ class _HomeScreenState extends State<HomeScreen> {
     );
     );
   }
   }
 }
 }
+
+class HomeScreenStackAdaptor extends HomeStackDelegate {
+  final BuildContext buildContext;
+  final HomeState homeState;
+
+  HomeScreenStackAdaptor({
+    required this.buildContext,
+    required this.homeState,
+  });
+
+  @override
+  void didDeleteStackWidget(ViewPB view) {
+    final homeService = HomeService();
+    homeService.readApp(appId: view.appId).then((result) {
+      result.fold(
+        (appPB) {
+          final List<ViewPB> views = appPB.belongings.items;
+          if (views.isNotEmpty) {
+            final lastView = views.last;
+            final plugin = makePlugin(
+              pluginType: lastView.pluginType,
+              data: lastView,
+            );
+            getIt<MenuSharedState>().latestOpenView = lastView;
+            getIt<HomeStackManager>().setPlugin(plugin);
+          } else {
+            getIt<MenuSharedState>().latestOpenView = null;
+            getIt<HomeStackManager>().setPlugin(BlankPagePlugin());
+          }
+        },
+        (err) => Log.error(err),
+      );
+    });
+  }
+}

+ 23 - 14
frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart

@@ -2,7 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/blank/blank.dart';
 import 'package:app_flowy/plugins/blank/blank.dart';
 import 'package:app_flowy/workspace/presentation/home/toast.dart';
 import 'package:app_flowy/workspace/presentation/home/toast.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra/theme.dart';
-import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 import 'package:provider/provider.dart';
 import 'package:time/time.dart';
 import 'package:time/time.dart';
@@ -17,14 +17,21 @@ import 'home_layout.dart';
 
 
 typedef NavigationCallback = void Function(String id);
 typedef NavigationCallback = void Function(String id);
 
 
-class HomeStack extends StatelessWidget {
-  const HomeStack({Key? key, required this.layout}) : super(key: key);
+abstract class HomeStackDelegate {
+  void didDeleteStackWidget(ViewPB view);
+}
 
 
+class HomeStack extends StatelessWidget {
+  final HomeStackDelegate delegate;
   final HomeLayout layout;
   final HomeLayout layout;
+  const HomeStack({
+    required this.delegate,
+    required this.layout,
+    Key? key,
+  }) : super(key: key);
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    Log.info('HomePage build');
     final theme = context.watch<AppTheme>();
     final theme = context.watch<AppTheme>();
     return Column(
     return Column(
       mainAxisAlignment: MainAxisAlignment.start,
       mainAxisAlignment: MainAxisAlignment.start,
@@ -34,7 +41,9 @@ class HomeStack extends StatelessWidget {
           child: Container(
           child: Container(
             color: theme.surface,
             color: theme.surface,
             child: FocusTraversalGroup(
             child: FocusTraversalGroup(
-              child: getIt<HomeStackManager>().stackWidget(),
+              child: getIt<HomeStackManager>().stackWidget(onDeleted: (view) {
+                delegate.didDeleteStackWidget(view);
+              }),
             ),
             ),
           ),
           ),
         ),
         ),
@@ -114,18 +123,18 @@ class HomeStackNotifier extends ChangeNotifier {
       return;
       return;
     }
     }
 
 
-    _plugin.display.notifier?.removeListener(notifyListeners);
+    _plugin.notifier?.isDisplayChanged.addListener(notifyListeners);
     _plugin.dispose();
     _plugin.dispose();
 
 
     _plugin = newPlugin;
     _plugin = newPlugin;
-    _plugin.display.notifier?.addListener(notifyListeners);
+    _plugin.notifier?.isDisplayChanged.removeListener(notifyListeners);
     notifyListeners();
     notifyListeners();
   }
   }
 
 
   Plugin get plugin => _plugin;
   Plugin get plugin => _plugin;
 }
 }
 
 
-// HomeStack is initialized as singleton to controll the page stack.
+// HomeStack is initialized as singleton to control the page stack.
 class HomeStackManager {
 class HomeStackManager {
   final HomeStackNotifier _notifier = HomeStackNotifier();
   final HomeStackNotifier _notifier = HomeStackNotifier();
   HomeStackManager();
   HomeStackManager();
@@ -140,7 +149,9 @@ class HomeStackManager {
     _notifier.plugin = newPlugin;
     _notifier.plugin = newPlugin;
   }
   }
 
 
-  void setStackWithId(String id) {}
+  void setStackWithId(String id) {
+    // Navigate to the page with id
+  }
 
 
   Widget stackTopBar({required HomeLayout layout}) {
   Widget stackTopBar({required HomeLayout layout}) {
     return MultiProvider(
     return MultiProvider(
@@ -156,18 +167,16 @@ class HomeStackManager {
     );
     );
   }
   }
 
 
-  Widget stackWidget() {
+  Widget stackWidget({required Function(ViewPB) onDeleted}) {
     return MultiProvider(
     return MultiProvider(
-      providers: [
-        ChangeNotifierProvider.value(value: _notifier),
-      ],
+      providers: [ChangeNotifierProvider.value(value: _notifier)],
       child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
       child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
         return FadingIndexedStack(
         return FadingIndexedStack(
           index: getIt<PluginSandbox>().indexOf(notifier.plugin.ty),
           index: getIt<PluginSandbox>().indexOf(notifier.plugin.ty),
           children: getIt<PluginSandbox>().supportPluginTypes.map((pluginType) {
           children: getIt<PluginSandbox>().supportPluginTypes.map((pluginType) {
             if (pluginType == notifier.plugin.ty) {
             if (pluginType == notifier.plugin.ty) {
               return notifier.plugin.display
               return notifier.plugin.display
-                  .buildWidget()
+                  .buildWidget(PluginContext(onDeleted: onDeleted))
                   .padding(horizontal: 40, vertical: 28);
                   .padding(horizontal: 40, vertical: 28);
             } else {
             } else {
               return const BlankPage();
               return const BlankPage();

+ 10 - 3
frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart

@@ -42,7 +42,12 @@ class _MenuAppState extends State<MenuApp> {
         listeners: [
         listeners: [
           BlocListener<AppBloc, AppState>(
           BlocListener<AppBloc, AppState>(
             listenWhen: (p, c) => p.latestCreatedView != c.latestCreatedView,
             listenWhen: (p, c) => p.latestCreatedView != c.latestCreatedView,
-            listener: (context, state) => getIt<MenuSharedState>().latestOpenView = state.latestCreatedView,
+            listener: (context, state) {
+              if (state.latestCreatedView != null) {
+                getIt<MenuSharedState>().latestOpenView =
+                    state.latestCreatedView;
+              }
+            },
           ),
           ),
           BlocListener<AppBloc, AppState>(
           BlocListener<AppBloc, AppState>(
             listenWhen: (p, c) => p.views != c.views,
             listenWhen: (p, c) => p.views != c.views,
@@ -65,7 +70,8 @@ class _MenuAppState extends State<MenuApp> {
     );
     );
   }
   }
 
 
-  ExpandableNotifier expandableWrapper(BuildContext context, AppViewDataContext viewDataContext) {
+  ExpandableNotifier expandableWrapper(
+      BuildContext context, AppViewDataContext viewDataContext) {
     return ExpandableNotifier(
     return ExpandableNotifier(
       controller: viewDataContext.expandController,
       controller: viewDataContext.expandController,
       child: ScrollOnExpand(
       child: ScrollOnExpand(
@@ -83,7 +89,8 @@ class _MenuAppState extends State<MenuApp> {
                 hasIcon: false,
                 hasIcon: false,
               ),
               ),
               header: ChangeNotifierProvider.value(
               header: ChangeNotifierProvider.value(
-                value: Provider.of<AppearanceSettingModel>(context, listen: true),
+                value:
+                    Provider.of<AppearanceSettingModel>(context, listen: true),
                 child: MenuAppHeader(widget.app),
                 child: MenuAppHeader(widget.app),
               ),
               ),
               expanded: ViewSection(appViewData: viewDataContext),
               expanded: ViewSection(appViewData: viewDataContext),

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

@@ -16,6 +16,7 @@ pub(crate) enum FolderNotification {
     ViewUpdated = 31,
     ViewUpdated = 31,
     ViewDeleted = 32,
     ViewDeleted = 32,
     ViewRestored = 33,
     ViewRestored = 33,
+    ViewMoveToTrash = 34,
     UserUnauthorized = 100,
     UserUnauthorized = 100,
     TrashUpdated = 1000,
     TrashUpdated = 1000,
 }
 }

+ 0 - 2
frontend/rust-lib/flowy-folder/src/manager.rs

@@ -251,8 +251,6 @@ pub trait ViewDataProcessor {
 
 
     fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError>;
     fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError>;
 
 
-    fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
-
     fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
     fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
 
 
     fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;
     fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;

+ 12 - 6
frontend/rust-lib/flowy-folder/src/services/view/controller.rs

@@ -125,7 +125,7 @@ impl ViewController {
     }
     }
 
 
     #[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
     #[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
-    pub(crate) async fn read_view_info(&self, view_id: ViewIdPB) -> Result<ViewInfoPB, FlowyError> {
+    pub(crate) async fn read_view_pb(&self, view_id: ViewIdPB) -> Result<ViewInfoPB, FlowyError> {
         let view_info = self
         let view_info = self
             .persistence
             .persistence
             .begin_transaction(|transaction| {
             .begin_transaction(|transaction| {
@@ -179,14 +179,20 @@ impl ViewController {
     }
     }
 
 
     #[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.value), err)]
     #[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.value), err)]
-    pub(crate) async fn delete_view(&self, params: TextBlockIdPB) -> Result<(), FlowyError> {
-        if let Some(view_id) = KV::get_str(LATEST_VIEW_ID) {
-            if view_id == params.value {
+    pub(crate) async fn move_view_to_trash(&self, params: TextBlockIdPB) -> Result<(), FlowyError> {
+        let view_id = params.value;
+        if let Some(latest_view_id) = KV::get_str(LATEST_VIEW_ID) {
+            if latest_view_id == view_id {
                 let _ = KV::remove(LATEST_VIEW_ID);
                 let _ = KV::remove(LATEST_VIEW_ID);
             }
             }
         }
         }
-        let processor = self.get_data_processor_from_view_id(&params.value).await?;
-        let _ = processor.delete_container(&params.value).await?;
+        let view_id_pb = ViewIdPB::from(view_id.as_str());
+        send_dart_notification(&view_id, FolderNotification::ViewMoveToTrash)
+            .payload(view_id_pb)
+            .send();
+
+        let processor = self.get_data_processor_from_view_id(&view_id).await?;
+        let _ = processor.close_container(&view_id).await?;
         Ok(())
         Ok(())
     }
     }
 
 

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

@@ -40,7 +40,7 @@ pub(crate) async fn read_view_info_handler(
     controller: AppData<Arc<ViewController>>,
     controller: AppData<Arc<ViewController>>,
 ) -> DataResult<ViewInfoPB, FlowyError> {
 ) -> DataResult<ViewInfoPB, FlowyError> {
     let view_id: ViewIdPB = data.into_inner();
     let view_id: ViewIdPB = data.into_inner();
-    let view_info = controller.read_view_info(view_id.clone()).await?;
+    let view_info = controller.read_view_pb(view_id.clone()).await?;
     data_result(view_info)
     data_result(view_info)
 }
 }
 
 
@@ -62,7 +62,7 @@ pub(crate) async fn delete_view_handler(
 ) -> Result<(), FlowyError> {
 ) -> Result<(), FlowyError> {
     let params: RepeatedViewIdPB = data.into_inner();
     let params: RepeatedViewIdPB = data.into_inner();
     for view_id in &params.items {
     for view_id in &params.items {
-        let _ = view_controller.delete_view(view_id.into()).await;
+        let _ = view_controller.move_view_to_trash(view_id.into()).await;
     }
     }
 
 
     let trash = view_controller
     let trash = view_controller

+ 0 - 11
frontend/rust-lib/flowy-grid/src/manager.rs

@@ -109,17 +109,6 @@ impl GridManager {
         Ok(())
         Ok(())
     }
     }
 
 
-    #[tracing::instrument(level = "debug", skip(self, grid_id), fields(doc_id), err)]
-    pub async fn delete_grid<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<()> {
-        let grid_id = grid_id.as_ref();
-        tracing::Span::current().record("grid_id", &grid_id);
-        self.grid_editors.remove(grid_id);
-        self.task_scheduler.write().await.unregister_handler(grid_id);
-        Ok(())
-    }
-
-    // pub fn update_grid_info()
-
     // #[tracing::instrument(level = "debug", skip(self), err)]
     // #[tracing::instrument(level = "debug", skip(self), err)]
     pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<GridRevisionEditor>> {
     pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<GridRevisionEditor>> {
         match self.grid_editors.get(grid_id) {
         match self.grid_editors.get(grid_id) {

+ 0 - 18
frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs

@@ -152,15 +152,6 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
         })
         })
     }
     }
 
 
-    fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
-        let manager = self.0.clone();
-        let view_id = view_id.to_string();
-        FutureResult::new(async move {
-            let _ = manager.close_text_editor(view_id)?;
-            Ok(())
-        })
-    }
-
     fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
     fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
         let manager = self.0.clone();
         let manager = self.0.clone();
         let view_id = view_id.to_string();
         let view_id = view_id.to_string();
@@ -230,15 +221,6 @@ impl ViewDataProcessor for GridViewDataProcessor {
         })
         })
     }
     }
 
 
-    fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
-        let grid_manager = self.0.clone();
-        let view_id = view_id.to_string();
-        FutureResult::new(async move {
-            let _ = grid_manager.delete_grid(view_id).await?;
-            Ok(())
-        })
-    }
-
     fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
     fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
         let grid_manager = self.0.clone();
         let grid_manager = self.0.clone();
         let view_id = view_id.to_string();
         let view_id = view_id.to_string();