Browse Source

feat: delete the view from the db when the view is deleted (#2703)

Nathan.fooo 1 year ago
parent
commit
a50c940282

+ 6 - 6
frontend/appflowy_tauri/src-tauri/Cargo.toml

@@ -34,12 +34,12 @@ default = ["custom-protocol"]
 custom-protocol = ["tauri/custom-protocol"]
 
 [patch.crates-io]
-collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
+collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
 
 #collab = { path = "../../AppFlowy-Collab/collab" }
 #collab-folder = { path = "../../AppFlowy-Collab/collab-folder" }

+ 10 - 10
frontend/rust-lib/Cargo.lock

@@ -85,7 +85,7 @@ checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
 [[package]]
 name = "appflowy-integrate"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "anyhow",
  "collab",
@@ -887,7 +887,7 @@ dependencies = [
 [[package]]
 name = "collab"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "anyhow",
  "bytes",
@@ -905,7 +905,7 @@ dependencies = [
 [[package]]
 name = "collab-client-ws"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "bytes",
  "collab-sync",
@@ -923,7 +923,7 @@ dependencies = [
 [[package]]
 name = "collab-database"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -949,7 +949,7 @@ dependencies = [
 [[package]]
 name = "collab-derive"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -961,7 +961,7 @@ dependencies = [
 [[package]]
 name = "collab-document"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "anyhow",
  "collab",
@@ -978,7 +978,7 @@ dependencies = [
 [[package]]
 name = "collab-folder"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "anyhow",
  "collab",
@@ -997,7 +997,7 @@ dependencies = [
 [[package]]
 name = "collab-persistence"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "bincode",
  "chrono",
@@ -1017,7 +1017,7 @@ dependencies = [
 [[package]]
 name = "collab-plugins"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -1047,7 +1047,7 @@ dependencies = [
 [[package]]
 name = "collab-sync"
 version = "0.1.0"
-source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
+source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cbc2e0#cbc2e0acb8420dc997921bb3f56b99f9975c2aab"
 dependencies = [
  "bytes",
  "collab",

+ 5 - 5
frontend/rust-lib/Cargo.toml

@@ -33,11 +33,11 @@ opt-level = 3
 incremental = false
 
 [patch.crates-io]
-collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178"  }
-collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178"  }
-collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
-appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "13b178" }
+collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0"  }
+collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0"  }
+collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
+appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cbc2e0" }
 
 #collab = { path = "../AppFlowy-Collab/collab" }
 #collab-folder = { path = "../AppFlowy-Collab/collab-folder" }

+ 26 - 2
frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs

@@ -5,6 +5,7 @@ use std::sync::Arc;
 use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
 use appflowy_integrate::RocksCollabDB;
 use bytes::Bytes;
+use tokio::sync::RwLock;
 
 use flowy_database2::entities::DatabaseLayoutPB;
 use flowy_database2::services::share::csv::CSVFormat;
@@ -24,7 +25,6 @@ use flowy_folder2::ViewLayout;
 use flowy_user::services::UserSession;
 use lib_dispatch::prelude::ToBytes;
 use lib_infra::future::FutureResult;
-use tokio::sync::RwLock;
 
 pub struct Folder2DepsResolver();
 impl Folder2DepsResolver {
@@ -121,7 +121,19 @@ impl FolderOperationHandler for DocumentFolderOperation {
     let manager = self.0.clone();
     let view_id = view_id.to_string();
     FutureResult::new(async move {
-      manager.close_document(view_id)?;
+      manager.close_document(&view_id)?;
+      Ok(())
+    })
+  }
+
+  fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
+    let manager = self.0.clone();
+    let view_id = view_id.to_string();
+    FutureResult::new(async move {
+      match manager.delete_document(&view_id) {
+        Ok(_) => tracing::trace!("Delete document: {}", view_id),
+        Err(e) => tracing::error!("Failed to delete document: {}", e),
+      }
       Ok(())
     })
   }
@@ -210,6 +222,18 @@ impl FolderOperationHandler for DatabaseFolderOperation {
     })
   }
 
+  fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
+    let database_manager = self.0.clone();
+    let view_id = view_id.to_string();
+    FutureResult::new(async move {
+      match database_manager.delete_database_view(&view_id).await {
+        Ok(_) => tracing::trace!("Delete database view: {}", view_id),
+        Err(e) => tracing::error!("Failed to delete database: {}", e),
+      }
+      Ok(())
+    })
+  }
+
   fn duplicate_view(&self, view_id: &str) -> FutureResult<Bytes, FlowyError> {
     let database_manager = self.0.clone();
     let view_id = view_id.to_owned();

+ 6 - 0
frontend/rust-lib/flowy-database2/src/manager.rs

@@ -132,6 +132,12 @@ impl DatabaseManager2 {
     Ok(())
   }
 
+  pub async fn delete_database_view(&self, view_id: &str) -> FlowyResult<()> {
+    let database = self.get_database_with_view_id(view_id).await?;
+    let _ = database.delete_database_view(view_id).await?;
+    Ok(())
+  }
+
   pub async fn duplicate_database(&self, view_id: &str) -> FlowyResult<Vec<u8>> {
     let database_data = self.with_user_database(Err(FlowyError::internal()), |database| {
       let data = database.get_database_duplicated_data(view_id)?;

+ 5 - 0
frontend/rust-lib/flowy-database2/src/notification.rs

@@ -1,5 +1,6 @@
 use flowy_derive::ProtoBuf_Enum;
 use flowy_notification::NotificationBuilder;
+
 const OBSERVABLE_CATEGORY: &str = "Grid";
 
 #[derive(ProtoBuf_Enum, Debug)]
@@ -37,6 +38,10 @@ pub enum DatabaseNotification {
   DidSetNewLayoutField = 81,
   // Trigger when the layout of the database is changed
   DidUpdateDatabaseLayout = 82,
+  // Trigger when the database view is deleted
+  DidDeleteDatabaseView = 83,
+  // Trigger when the database view is moved to trash
+  DidMoveDatabaseViewToTrash = 84,
 }
 
 impl std::default::Default for DatabaseNotification {

+ 1 - 1
frontend/rust-lib/flowy-database2/src/services/cell/cell_operation.rs

@@ -312,7 +312,7 @@ impl<'a> CellBuilder<'a> {
       .collect::<HashMap<String, &Field>>();
 
     let mut cells = Cells::new();
-    for (field_id, cell_str) in cell_by_field_id.clone() {
+    for (field_id, cell_str) in cell_by_field_id {
       if let Some(field) = field_maps.get(&field_id) {
         let field_type = FieldType::from(field.field_type);
         match field_type {

+ 9 - 1
frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs

@@ -125,6 +125,14 @@ impl DatabaseEditor {
     Ok(())
   }
 
+  /// Returns the delete view ids.
+  /// If the view is inline view, all the reference views will be deleted. So the return value
+  /// will be the reference view ids and the inline view id. Otherwise, the return value will
+  /// be the view id.
+  pub async fn delete_database_view(&self, view_id: &str) -> FlowyResult<Vec<String>> {
+    Ok(self.database.lock().delete_view(view_id))
+  }
+
   pub async fn update_group_setting(
     &self,
     view_id: &str,
@@ -942,7 +950,7 @@ impl DatabaseEditor {
     let view = database_view
       .get_view()
       .await
-      .ok_or_else(|| FlowyError::record_not_found())?;
+      .ok_or_else(FlowyError::record_not_found)?;
     let rows = database_view.v_get_rows().await;
     let (database_id, fields) = {
       let database = self.database.lock();

+ 2 - 2
frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs

@@ -108,7 +108,7 @@ pub(crate) async fn get_cell_for_row(
 
   let cell_data = match &row_cell.cell {
     None => None,
-    Some(cell) => handler.get_cell_data(&cell, &field_type, &field).ok(),
+    Some(cell) => handler.get_cell_data(cell, &field_type, &field).ok(),
   };
   Some(RowSingleCellData {
     row_id: row_cell.row_id.clone(),
@@ -133,7 +133,7 @@ pub(crate) async fn get_cells_for_field(
         .map(|row_cell| {
           let cell_data = match &row_cell.cell {
             None => None,
-            Some(cell) => handler.get_cell_data(&cell, &field_type, &field).ok(),
+            Some(cell) => handler.get_cell_data(cell, &field_type, &field).ok(),
           };
           RowSingleCellData {
             row_id: row_cell.row_id.clone(),

+ 1 - 1
frontend/rust-lib/flowy-document2/src/event_handler.rs

@@ -51,7 +51,7 @@ pub(crate) async fn close_document_handler(
   manager: AFPluginState<Arc<DocumentManager>>,
 ) -> FlowyResult<()> {
   let context = data.into_inner();
-  manager.close_document(context.document_id)?;
+  manager.close_document(&context.document_id)?;
   Ok(())
 }
 

+ 14 - 2
frontend/rust-lib/flowy-document2/src/manager.rs

@@ -3,6 +3,7 @@ use std::{collections::HashMap, sync::Arc};
 use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
 use appflowy_integrate::RocksCollabDB;
 use collab_document::blocks::DocumentData;
+use collab_document::YrsDocAction;
 use parking_lot::RwLock;
 
 use flowy_error::{FlowyError, FlowyResult};
@@ -96,8 +97,19 @@ impl DocumentManager {
     Ok(document)
   }
 
-  pub fn close_document(&self, doc_id: String) -> FlowyResult<()> {
-    self.documents.write().remove(&doc_id);
+  pub fn close_document(&self, doc_id: &str) -> FlowyResult<()> {
+    self.documents.write().remove(doc_id);
+    Ok(())
+  }
+
+  pub fn delete_document(&self, doc_id: &str) -> FlowyResult<()> {
+    let uid = self.user.user_id()?;
+    let db = self.user.collab_db()?;
+    let _ = db.with_write_txn(|txn| {
+      txn.delete_doc(uid, &doc_id)?;
+      Ok(())
+    });
+    self.documents.write().remove(doc_id);
     Ok(())
   }
 }

+ 10 - 9
frontend/rust-lib/flowy-document2/tests/document/document_test.rs

@@ -1,14 +1,15 @@
 use std::{collections::HashMap, sync::Arc, vec};
 
 use collab_document::blocks::{Block, BlockAction, BlockActionPayload, BlockActionType};
-use flowy_document2::document_block_keys::PARAGRAPH_BLOCK_TYPE;
 use nanoid::nanoid;
 use serde_json::{json, to_value, Value};
 
-use crate::document::util::default_collab_builder;
+use flowy_document2::document_block_keys::PARAGRAPH_BLOCK_TYPE;
 use flowy_document2::document_data::default_document_data;
 use flowy_document2::manager::DocumentManager;
 
+use crate::document::util::default_collab_builder;
+
 use super::util::FakeUser;
 
 #[test]
@@ -33,7 +34,7 @@ fn restore_document() {
     .get_document()
     .unwrap();
   // close a document
-  _ = manager.close_document(doc_id.clone());
+  _ = manager.close_document(&doc_id);
   assert_eq!(data_b, data);
 
   // restore
@@ -46,7 +47,7 @@ fn restore_document() {
     .get_document()
     .unwrap();
   // close a document
-  _ = manager.close_document(doc_id);
+  _ = manager.close_document(&doc_id);
 
   assert_eq!(data_b, data);
 }
@@ -87,7 +88,7 @@ fn document_apply_insert_action() {
   document.lock().apply_action(vec![insert_text_action]);
   let data_a = document.lock().get_document().unwrap();
   // close the original document
-  _ = manager.close_document(doc_id.clone());
+  _ = manager.close_document(&doc_id);
 
   // re-open the document
   let data_b = manager
@@ -97,7 +98,7 @@ fn document_apply_insert_action() {
     .get_document()
     .unwrap();
   // close a document
-  _ = manager.close_document(doc_id);
+  _ = manager.close_document(&doc_id);
 
   assert_eq!(data_b, data_a);
 }
@@ -135,7 +136,7 @@ fn document_apply_update_page_action() {
   tracing::trace!("{:?}", &actions);
   document.lock().apply_action(actions);
   let page_block_old = document.lock().get_block(&data.page_id).unwrap();
-  _ = manager.close_document(doc_id.clone());
+  _ = manager.close_document(&doc_id);
 
   // re-open the document
   let document = manager.open_document(doc_id).unwrap();
@@ -203,12 +204,12 @@ fn document_apply_update_action() {
   };
   document.lock().apply_action(vec![update_text_action]);
   // close the original document
-  _ = manager.close_document(doc_id.clone());
+  _ = manager.close_document(&doc_id);
 
   // re-open the document
   let document = manager.open_document(doc_id.clone()).unwrap();
   let block = document.lock().get_block(&text_block_id).unwrap();
   assert_eq!(block.data, updated_text_block_data);
   // close a document
-  _ = manager.close_document(doc_id);
+  _ = manager.close_document(&doc_id);
 }

+ 6 - 5
frontend/rust-lib/flowy-folder2/src/event_handler.rs

@@ -1,3 +1,8 @@
+use std::sync::Arc;
+
+use flowy_error::FlowyError;
+use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
+
 use crate::entities::{
   view_pb_without_child_views, CreateViewParams, CreateViewPayloadPB, CreateWorkspaceParams,
   CreateWorkspacePayloadPB, ImportPB, MoveFolderItemPayloadPB, MoveViewParams, RepeatedTrashIdPB,
@@ -6,11 +11,7 @@ use crate::entities::{
   WorkspaceSettingPB,
 };
 use crate::manager::Folder2Manager;
-
 use crate::share::ImportParams;
-use flowy_error::FlowyError;
-use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
-use std::sync::Arc;
 
 #[tracing::instrument(level = "debug", skip(data, folder), err)]
 pub(crate) async fn create_workspace_handler(
@@ -187,7 +188,7 @@ pub(crate) async fn delete_trash_handler(
 ) -> Result<(), FlowyError> {
   let trash_ids = identifiers.into_inner().items;
   for trash_id in trash_ids {
-    folder.delete_trash(&trash_id.id).await;
+    let _ = folder.delete_trash(&trash_id.id).await;
   }
   Ok(())
 }

+ 26 - 25
frontend/rust-lib/flowy-folder2/src/manager.rs

@@ -1,24 +1,22 @@
 use std::collections::{HashMap, HashSet};
-
 use std::ops::Deref;
 use std::sync::{Arc, Weak};
 
 use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
 use collab::core::collab_state::CollabState;
-
 use collab_folder::core::{
   Folder, FolderContext, TrashChange, TrashChangeReceiver, TrashInfo, TrashRecord, View,
   ViewChange, ViewChangeReceiver, ViewLayout, Workspace,
 };
 use parking_lot::Mutex;
+use tokio_stream::wrappers::WatchStream;
+use tokio_stream::StreamExt;
 use tracing::{event, Level};
 
-use crate::deps::{FolderCloudService, FolderUser};
 use flowy_error::{ErrorCode, FlowyError, FlowyResult};
 use lib_infra::util::timestamp;
-use tokio_stream::wrappers::WatchStream;
-use tokio_stream::StreamExt;
 
+use crate::deps::{FolderCloudService, FolderUser};
 use crate::entities::{
   view_pb_with_child_views, CreateViewParams, CreateWorkspaceParams, RepeatedTrashPB,
   RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, ViewPB,
@@ -302,12 +300,6 @@ impl Folder2Manager {
     }
   }
 
-  #[tracing::instrument(level = "debug", skip(self, view_id), err)]
-  pub async fn delete_view(&self, view_id: &str) -> FlowyResult<()> {
-    self.with_folder((), |folder| folder.views.delete_views(vec![view_id]));
-    Ok(())
-  }
-
   /// Move the view to trash. If the view is the current view, then set the current view to empty.
   /// When the view is moved to trash, all the child views will be moved to trash as well.
   #[tracing::instrument(level = "debug", skip(self), err)]
@@ -453,27 +445,36 @@ impl Folder2Manager {
     });
   }
 
-  #[tracing::instrument(level = "trace", skip(self))]
-  pub(crate) async fn delete_trash(&self, trash_id: &str) {
-    self.with_folder((), |folder| {
-      folder.trash.delete_trash(vec![trash_id]);
-      folder.views.delete_views(vec![trash_id]);
-    })
-  }
-
+  /// Delete all the trash permanently.
   #[tracing::instrument(level = "trace", skip(self))]
   pub(crate) async fn delete_all_trash(&self) {
-    self.with_folder((), |folder| {
-      let trash = folder.trash.get_all_trash();
-      folder.trash.clear();
-      folder.views.delete_views(trash);
-    });
-
+    let deleted_trash = self.with_folder(vec![], |folder| folder.trash.get_all_trash());
+    for trash in deleted_trash {
+      let _ = self.delete_trash(&trash.id).await;
+    }
     send_notification("trash", FolderNotification::DidUpdateTrash)
       .payload(RepeatedTrashPB { items: vec![] })
       .send();
   }
 
+  /// Delete the trash permanently.
+  /// Delete the view will delete all the resources that the view holds. For example, if the view
+  /// is a database view. Then the database will be deleted as well.
+  #[tracing::instrument(level = "debug", skip(self, view_id), err)]
+  pub async fn delete_trash(&self, view_id: &str) -> FlowyResult<()> {
+    let view = self.with_folder(None, |folder| folder.views.get_view(view_id));
+    self.with_folder((), |folder| {
+      folder.trash.delete_trash(vec![view_id]);
+      folder.views.delete_views(vec![view_id]);
+    });
+    if let Some(view) = view {
+      if let Ok(handler) = self.get_handler(&view.layout) {
+        handler.delete_view(view_id).await?;
+      }
+    }
+    Ok(())
+  }
+
   pub(crate) async fn import(&self, import_data: ImportParams) -> FlowyResult<View> {
     if import_data.data.is_none() && import_data.file_path.is_none() {
       return Err(FlowyError::new(

+ 12 - 6
frontend/rust-lib/flowy-folder2/src/view_operation.rs

@@ -1,17 +1,19 @@
-use crate::entities::{CreateViewParams, ViewLayoutPB};
+use std::collections::HashMap;
+use std::future::Future;
+use std::sync::Arc;
+
 use bytes::Bytes;
+pub use collab_folder::core::View;
 use collab_folder::core::{RepeatedView, ViewIdentifier, ViewLayout};
+use tokio::sync::RwLock;
+
 use flowy_error::FlowyError;
 use lib_infra::future::FutureResult;
 use lib_infra::util::timestamp;
 
-use std::collections::HashMap;
-use std::future::Future;
-use std::sync::Arc;
+use crate::entities::{CreateViewParams, ViewLayoutPB};
 
 pub type ViewData = Bytes;
-pub use collab_folder::core::View;
-use tokio::sync::RwLock;
 
 /// A builder for creating a view for a workspace.
 /// The views created by this builder will be the first level views of the workspace.
@@ -157,6 +159,10 @@ pub trait FolderOperationHandler {
   /// the backend
   fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError>;
 
+  /// Called when the view is deleted.
+  /// This will called after the view is deleted from the trash.
+  fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError>;
+
   /// Returns the [ViewData] that can be used to create the same view.
   fn duplicate_view(&self, view_id: &str) -> FutureResult<ViewData, FlowyError>;