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

This commit is contained in:
Nathan.fooo 2023-06-05 09:42:11 +08:00 committed by GitHub
parent bec8122178
commit a50c940282
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 143 additions and 79 deletions

View File

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

View File

@ -85,7 +85,7 @@ checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]] [[package]]
name = "appflowy-integrate" name = "appflowy-integrate"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -887,7 +887,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -905,7 +905,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-client-ws" name = "collab-client-ws"
version = "0.1.0" 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 = [ dependencies = [
"bytes", "bytes",
"collab-sync", "collab-sync",
@ -923,7 +923,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -949,7 +949,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-derive" name = "collab-derive"
version = "0.1.0" 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 = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -961,7 +961,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -978,7 +978,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -997,7 +997,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-persistence" name = "collab-persistence"
version = "0.1.0" 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 = [ dependencies = [
"bincode", "bincode",
"chrono", "chrono",
@ -1017,7 +1017,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1047,7 +1047,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-sync" name = "collab-sync"
version = "0.1.0" 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 = [ dependencies = [
"bytes", "bytes",
"collab", "collab",

View File

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

View File

@ -5,6 +5,7 @@ use std::sync::Arc;
use appflowy_integrate::collab_builder::AppFlowyCollabBuilder; use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
use appflowy_integrate::RocksCollabDB; use appflowy_integrate::RocksCollabDB;
use bytes::Bytes; use bytes::Bytes;
use tokio::sync::RwLock;
use flowy_database2::entities::DatabaseLayoutPB; use flowy_database2::entities::DatabaseLayoutPB;
use flowy_database2::services::share::csv::CSVFormat; use flowy_database2::services::share::csv::CSVFormat;
@ -24,7 +25,6 @@ use flowy_folder2::ViewLayout;
use flowy_user::services::UserSession; use flowy_user::services::UserSession;
use lib_dispatch::prelude::ToBytes; use lib_dispatch::prelude::ToBytes;
use lib_infra::future::FutureResult; use lib_infra::future::FutureResult;
use tokio::sync::RwLock;
pub struct Folder2DepsResolver(); pub struct Folder2DepsResolver();
impl Folder2DepsResolver { impl Folder2DepsResolver {
@ -121,7 +121,19 @@ impl FolderOperationHandler for DocumentFolderOperation {
let manager = self.0.clone(); let manager = self.0.clone();
let view_id = view_id.to_string(); let view_id = view_id.to_string();
FutureResult::new(async move { 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(()) 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> { fn duplicate_view(&self, view_id: &str) -> FutureResult<Bytes, FlowyError> {
let database_manager = self.0.clone(); let database_manager = self.0.clone();
let view_id = view_id.to_owned(); let view_id = view_id.to_owned();

View File

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

View File

@ -1,5 +1,6 @@
use flowy_derive::ProtoBuf_Enum; use flowy_derive::ProtoBuf_Enum;
use flowy_notification::NotificationBuilder; use flowy_notification::NotificationBuilder;
const OBSERVABLE_CATEGORY: &str = "Grid"; const OBSERVABLE_CATEGORY: &str = "Grid";
#[derive(ProtoBuf_Enum, Debug)] #[derive(ProtoBuf_Enum, Debug)]
@ -37,6 +38,10 @@ pub enum DatabaseNotification {
DidSetNewLayoutField = 81, DidSetNewLayoutField = 81,
// Trigger when the layout of the database is changed // Trigger when the layout of the database is changed
DidUpdateDatabaseLayout = 82, 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 { impl std::default::Default for DatabaseNotification {

View File

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

View File

@ -125,6 +125,14 @@ impl DatabaseEditor {
Ok(()) 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( pub async fn update_group_setting(
&self, &self,
view_id: &str, view_id: &str,
@ -942,7 +950,7 @@ impl DatabaseEditor {
let view = database_view let view = database_view
.get_view() .get_view()
.await .await
.ok_or_else(|| FlowyError::record_not_found())?; .ok_or_else(FlowyError::record_not_found)?;
let rows = database_view.v_get_rows().await; let rows = database_view.v_get_rows().await;
let (database_id, fields) = { let (database_id, fields) = {
let database = self.database.lock(); let database = self.database.lock();

View File

@ -108,7 +108,7 @@ pub(crate) async fn get_cell_for_row(
let cell_data = match &row_cell.cell { let cell_data = match &row_cell.cell {
None => None, 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 { Some(RowSingleCellData {
row_id: row_cell.row_id.clone(), row_id: row_cell.row_id.clone(),
@ -133,7 +133,7 @@ pub(crate) async fn get_cells_for_field(
.map(|row_cell| { .map(|row_cell| {
let cell_data = match &row_cell.cell { let cell_data = match &row_cell.cell {
None => None, 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 { RowSingleCellData {
row_id: row_cell.row_id.clone(), row_id: row_cell.row_id.clone(),

View File

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

View File

@ -3,6 +3,7 @@ use std::{collections::HashMap, sync::Arc};
use appflowy_integrate::collab_builder::AppFlowyCollabBuilder; use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
use appflowy_integrate::RocksCollabDB; use appflowy_integrate::RocksCollabDB;
use collab_document::blocks::DocumentData; use collab_document::blocks::DocumentData;
use collab_document::YrsDocAction;
use parking_lot::RwLock; use parking_lot::RwLock;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
@ -96,8 +97,19 @@ impl DocumentManager {
Ok(document) Ok(document)
} }
pub fn close_document(&self, doc_id: String) -> FlowyResult<()> { pub fn close_document(&self, doc_id: &str) -> FlowyResult<()> {
self.documents.write().remove(&doc_id); 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(()) Ok(())
} }
} }

View File

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

View File

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

View File

@ -1,24 +1,22 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::ops::Deref; use std::ops::Deref;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use appflowy_integrate::collab_builder::AppFlowyCollabBuilder; use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
use collab::core::collab_state::CollabState; use collab::core::collab_state::CollabState;
use collab_folder::core::{ use collab_folder::core::{
Folder, FolderContext, TrashChange, TrashChangeReceiver, TrashInfo, TrashRecord, View, Folder, FolderContext, TrashChange, TrashChangeReceiver, TrashInfo, TrashRecord, View,
ViewChange, ViewChangeReceiver, ViewLayout, Workspace, ViewChange, ViewChangeReceiver, ViewLayout, Workspace,
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
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::wrappers::WatchStream;
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tracing::{event, Level};
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use lib_infra::util::timestamp;
use crate::deps::{FolderCloudService, FolderUser};
use crate::entities::{ use crate::entities::{
view_pb_with_child_views, CreateViewParams, CreateWorkspaceParams, RepeatedTrashPB, view_pb_with_child_views, CreateViewParams, CreateWorkspaceParams, RepeatedTrashPB,
RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, ViewPB, 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. /// 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. /// 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)] #[tracing::instrument(level = "debug", skip(self), err)]
@ -453,27 +445,36 @@ impl Folder2Manager {
}); });
} }
#[tracing::instrument(level = "trace", skip(self))] /// Delete all the trash permanently.
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]);
})
}
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn delete_all_trash(&self) { pub(crate) async fn delete_all_trash(&self) {
self.with_folder((), |folder| { let deleted_trash = self.with_folder(vec![], |folder| folder.trash.get_all_trash());
let trash = folder.trash.get_all_trash(); for trash in deleted_trash {
folder.trash.clear(); let _ = self.delete_trash(&trash.id).await;
folder.views.delete_views(trash); }
});
send_notification("trash", FolderNotification::DidUpdateTrash) send_notification("trash", FolderNotification::DidUpdateTrash)
.payload(RepeatedTrashPB { items: vec![] }) .payload(RepeatedTrashPB { items: vec![] })
.send(); .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> { pub(crate) async fn import(&self, import_data: ImportParams) -> FlowyResult<View> {
if import_data.data.is_none() && import_data.file_path.is_none() { if import_data.data.is_none() && import_data.file_path.is_none() {
return Err(FlowyError::new( return Err(FlowyError::new(

View File

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