use crate::errors::{internal_sync_error, SyncError, SyncResult}; use crate::util::cal_diff; use database_model::{ DatabaseViewRevision, FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision, LayoutRevision, SortRevision, }; use flowy_sync::util::make_operations_from_revisions; use lib_infra::util::md5; use lib_ot::core::{DeltaBuilder, DeltaOperations, EmptyAttributes, OperationTransform}; use revision_model::Revision; use std::sync::Arc; pub type GridViewOperations = DeltaOperations; pub type GridViewOperationsBuilder = DeltaBuilder; #[derive(Debug, Clone)] pub struct DatabaseViewRevisionPad { view: Arc, operations: GridViewOperations, } impl std::ops::Deref for DatabaseViewRevisionPad { type Target = DatabaseViewRevision; fn deref(&self) -> &Self::Target { &self.view } } impl DatabaseViewRevisionPad { // For the moment, the view_id is equal to grid_id. The database_id represents the database id. // A database can be referenced by multiple views. pub fn new(database_id: String, view_id: String, layout: LayoutRevision) -> Self { let view = Arc::new(DatabaseViewRevision::new(database_id, view_id, layout)); let json = serde_json::to_string(&view).unwrap(); let operations = GridViewOperationsBuilder::new().insert(&json).build(); Self { view, operations } } pub fn from_operations(operations: GridViewOperations) -> SyncResult { if operations.is_empty() { return Err(SyncError::record_not_found().context("Unexpected empty operations")); } let s = operations.content()?; let view: DatabaseViewRevision = serde_json::from_str(&s).map_err(|e| { let msg = format!("Deserialize operations to GridViewRevision failed: {}", e); tracing::error!("parsing json: {}", s); SyncError::internal().context(msg) })?; Ok(Self { view: Arc::new(view), operations, }) } pub fn from_revisions(revisions: Vec) -> SyncResult { let operations: GridViewOperations = make_operations_from_revisions(revisions)?; Self::from_operations(operations) } pub fn get_groups_by_field_revs( &self, field_revs: &[Arc], ) -> Vec> { self.groups.get_objects_by_field_revs(field_revs) } pub fn get_all_groups(&self) -> Vec> { self.groups.get_all_objects() } #[tracing::instrument(level = "trace", skip_all, err)] pub fn insert_or_update_group_configuration( &mut self, field_id: &str, field_type: &FieldTypeRevision, group_configuration_rev: GroupConfigurationRevision, ) -> SyncResult> { self.modify(|view| { // Only save one group view.groups.clear(); view .groups .add_object(field_id, field_type, group_configuration_rev); Ok(Some(())) }) } #[tracing::instrument(level = "trace", skip_all)] pub fn contains_group(&self, field_id: &str, field_type: &FieldTypeRevision) -> bool { self.view.groups.get_objects(field_id, field_type).is_some() } #[tracing::instrument(level = "trace", skip_all, err)] pub fn with_mut_group( &mut self, field_id: &str, field_type: &FieldTypeRevision, configuration_id: &str, mut_configuration_fn: F, ) -> SyncResult> { self.modify( |view| match view.groups.get_mut_objects(field_id, field_type) { None => Ok(None), Some(configurations_revs) => { for configuration_rev in configurations_revs { if configuration_rev.id == configuration_id { mut_configuration_fn(Arc::make_mut(configuration_rev)); return Ok(Some(())); } } Ok(None) }, }, ) } pub fn delete_group( &mut self, group_id: &str, field_id: &str, field_type: &FieldTypeRevision, ) -> SyncResult> { self.modify(|view| { if let Some(groups) = view.groups.get_mut_objects(field_id, field_type) { groups.retain(|group| group.id != group_id); Ok(Some(())) } else { Ok(None) } }) } pub fn get_all_sorts(&self, _field_revs: &[Arc]) -> Vec> { self.sorts.get_all_objects() } /// For the moment, a field type only have one filter. pub fn get_sorts( &self, field_id: &str, field_type_rev: &FieldTypeRevision, ) -> Vec> { self .sorts .get_objects(field_id, field_type_rev) .unwrap_or_default() } pub fn get_sort( &self, field_id: &str, field_type_rev: &FieldTypeRevision, sort_id: &str, ) -> Option> { self .sorts .get_object(field_id, field_type_rev, |sort| sort.id == sort_id) } pub fn insert_sort( &mut self, field_id: &str, sort_rev: SortRevision, ) -> SyncResult> { self.modify(|view| { let field_type = sort_rev.field_type; view.sorts.add_object(field_id, &field_type, sort_rev); Ok(Some(())) }) } pub fn update_sort( &mut self, field_id: &str, sort_rev: SortRevision, ) -> SyncResult> { self.modify(|view| { if let Some(sort) = view .sorts .get_mut_object(field_id, &sort_rev.field_type, |sort| { sort.id == sort_rev.id }) { let sort = Arc::make_mut(sort); sort.condition = sort_rev.condition; Ok(Some(())) } else { Ok(None) } }) } pub fn delete_sort>( &mut self, sort_id: &str, field_id: &str, field_type: T, ) -> SyncResult> { let field_type = field_type.into(); self.modify(|view| { if let Some(sorts) = view.sorts.get_mut_objects(field_id, &field_type) { sorts.retain(|sort| sort.id != sort_id); Ok(Some(())) } else { Ok(None) } }) } pub fn delete_all_sorts(&mut self) -> SyncResult> { self.modify(|view| { view.sorts.clear(); Ok(Some(())) }) } pub fn get_all_filters(&self, field_revs: &[Arc]) -> Vec> { self.filters.get_objects_by_field_revs(field_revs) } /// For the moment, a field type only have one filter. pub fn get_filters( &self, field_id: &str, field_type_rev: &FieldTypeRevision, ) -> Vec> { self .filters .get_objects(field_id, field_type_rev) .unwrap_or_default() } pub fn get_filter( &self, field_id: &str, field_type_rev: &FieldTypeRevision, filter_id: &str, ) -> Option> { self .filters .get_object(field_id, field_type_rev, |filter| filter.id == filter_id) } pub fn insert_filter( &mut self, field_id: &str, filter_rev: FilterRevision, ) -> SyncResult> { self.modify(|view| { let field_type = filter_rev.field_type; view.filters.add_object(field_id, &field_type, filter_rev); Ok(Some(())) }) } pub fn update_filter( &mut self, field_id: &str, filter_rev: FilterRevision, ) -> SyncResult> { self.modify(|view| { if let Some(filter) = view .filters .get_mut_object(field_id, &filter_rev.field_type, |filter| { filter.id == filter_rev.id }) { let filter = Arc::make_mut(filter); filter.condition = filter_rev.condition; filter.content = filter_rev.content; Ok(Some(())) } else { Ok(None) } }) } pub fn delete_filter>( &mut self, filter_id: &str, field_id: &str, field_type: T, ) -> SyncResult> { let field_type = field_type.into(); self.modify(|view| { if let Some(filters) = view.filters.get_mut_objects(field_id, &field_type) { filters.retain(|filter| filter.id != filter_id); Ok(Some(())) } else { Ok(None) } }) } pub fn json_str(&self) -> SyncResult { make_grid_view_rev_json_str(&self.view) } pub fn layout(&self) -> LayoutRevision { self.layout.clone() } fn modify(&mut self, f: F) -> SyncResult> where F: FnOnce(&mut DatabaseViewRevision) -> SyncResult>, { let cloned_view = self.view.clone(); match f(Arc::make_mut(&mut self.view))? { None => Ok(None), Some(_) => { let old = make_grid_view_rev_json_str(&cloned_view)?; let new = self.json_str()?; match cal_diff::(old, new) { None => Ok(None), Some(operations) => { self.operations = self.operations.compose(&operations)?; let md5 = md5(&self.operations.json_bytes()); Ok(Some(GridViewRevisionChangeset { operations, md5 })) }, } }, } } } #[derive(Debug)] pub struct GridViewRevisionChangeset { pub operations: GridViewOperations, pub md5: String, } pub fn make_grid_view_rev_json_str(grid_revision: &DatabaseViewRevision) -> SyncResult { let json = serde_json::to_string(grid_revision).map_err(|err| { internal_sync_error(format!("Serialize grid view to json str failed. {:?}", err)) })?; Ok(json) } pub fn make_grid_view_operations(grid_view: &DatabaseViewRevision) -> GridViewOperations { let json = serde_json::to_string(grid_view).unwrap(); GridViewOperationsBuilder::new().insert(&json).build() }