diff --git a/frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart index 63accc38d0..7a2bbe0cb3 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart @@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; -typedef GridBlockUpdateNotifierValue = Either, FlowyError>; +typedef GridBlockUpdateNotifierValue = Either, FlowyError>; class GridBlockListener { final String blockId; @@ -33,7 +33,7 @@ class GridBlockListener { switch (ty) { case GridNotification.DidUpdateGridBlock: result.fold( - (payload) => _rowsUpdateNotifier?.value = left([GridRowsChangeset.fromBuffer(payload)]), + (payload) => _rowsUpdateNotifier?.value = left([GridBlockChangeset.fromBuffer(payload)]), (error) => _rowsUpdateNotifier?.value = right(error), ); break; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 8a683e8d91..78e4e6715f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -57,17 +57,19 @@ class GridRowCacheService { _deleteRows(changeset.deletedRows); _insertRows(changeset.insertedRows); _updateRows(changeset.updatedRows); + _hideRows(changeset.hideRows); + _showRows(changeset.visibleRows); } } - void _deleteRows(List deletedRows) { + void _deleteRows(List deletedRows) { if (deletedRows.isEmpty) { return; } final List newRows = []; final DeletedIndexs deletedIndex = []; - final Map deletedRowByRowId = {for (var e in deletedRows) e.rowId: e}; + final Map deletedRowByRowId = {for (var rowId in deletedRows) rowId: rowId}; _rows.asMap().forEach((index, row) { if (deletedRowByRowId[row.rowId] == null) { @@ -80,7 +82,7 @@ class GridRowCacheService { _notifier.receive(GridRowChangeReason.delete(deletedIndex)); } - void _insertRows(List insertRows) { + void _insertRows(List insertRows) { if (insertRows.isEmpty) { return; } @@ -93,7 +95,7 @@ class GridRowCacheService { rowId: insertRow.rowId, ); insertIndexs.add(insertIndex); - newRows.insert(insertRow.index, (buildGridRow(insertRow.rowId, insertIndex.row.height))); + newRows.insert(insertRow.index, (buildGridRow(insertRow.rowId, insertRow.height.toDouble()))); } _notifier.receive(GridRowChangeReason.insert(insertIndexs)); @@ -121,6 +123,10 @@ class GridRowCacheService { _notifier.receive(GridRowChangeReason.update(updatedIndexs)); } + void _hideRows(List hideRows) {} + + void _showRows(List visibleRows) {} + void onRowsChanged( void Function(GridRowChangeReason) onRowChanged, ) { diff --git a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs index 9c856340ac..9cfdbc088c 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs @@ -1,4 +1,3 @@ -use crate::entities::GridRowId; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; @@ -11,11 +10,11 @@ pub struct GridBlock { pub id: String, #[pb(index = 2)] - pub row_infos: Vec, + pub row_infos: Vec, } impl GridBlock { - pub fn new(block_id: &str, row_orders: Vec) -> Self { + pub fn new(block_id: &str, row_orders: Vec) -> Self { Self { id: block_id.to_owned(), row_infos: row_orders, @@ -24,7 +23,7 @@ impl GridBlock { } #[derive(Debug, Default, Clone, ProtoBuf)] -pub struct BlockRowInfo { +pub struct RowInfo { #[pb(index = 1)] pub block_id: String, @@ -35,7 +34,7 @@ pub struct BlockRowInfo { pub height: i32, } -impl BlockRowInfo { +impl RowInfo { pub fn row_id(&self) -> &str { &self.row_id } @@ -45,7 +44,7 @@ impl BlockRowInfo { } } -impl std::convert::From<&RowRevision> for BlockRowInfo { +impl std::convert::From<&RowRevision> for RowInfo { fn from(rev: &RowRevision) -> Self { Self { block_id: rev.block_id.clone(), @@ -55,7 +54,7 @@ impl std::convert::From<&RowRevision> for BlockRowInfo { } } -impl std::convert::From<&Arc> for BlockRowInfo { +impl std::convert::From<&Arc> for RowInfo { fn from(rev: &Arc) -> Self { Self { block_id: rev.block_id.clone(), @@ -140,8 +139,8 @@ impl UpdatedRow { } } -impl std::convert::From for InsertedRow { - fn from(row_info: BlockRowInfo) -> Self { +impl std::convert::From for InsertedRow { + fn from(row_info: RowInfo) -> Self { Self { row_id: row_info.row_id, block_id: row_info.block_id, @@ -153,7 +152,7 @@ impl std::convert::From for InsertedRow { impl std::convert::From<&RowRevision> for InsertedRow { fn from(row: &RowRevision) -> Self { - let row_order = BlockRowInfo::from(row); + let row_order = RowInfo::from(row); Self::from(row_order) } } @@ -167,36 +166,39 @@ pub struct GridBlockChangeset { pub inserted_rows: Vec, #[pb(index = 3)] - pub deleted_rows: Vec, + pub deleted_rows: Vec, #[pb(index = 4)] pub updated_rows: Vec, + + #[pb(index = 5)] + pub visible_rows: Vec, + + #[pb(index = 6)] + pub hide_rows: Vec, } impl GridBlockChangeset { pub fn insert(block_id: &str, inserted_rows: Vec) -> Self { Self { block_id: block_id.to_owned(), inserted_rows, - deleted_rows: vec![], - updated_rows: vec![], + ..Default::default() } } - pub fn delete(block_id: &str, deleted_rows: Vec) -> Self { + pub fn delete(block_id: &str, deleted_rows: Vec) -> Self { Self { block_id: block_id.to_owned(), - inserted_rows: vec![], deleted_rows, - updated_rows: vec![], + ..Default::default() } } pub fn update(block_id: &str, updated_rows: Vec) -> Self { Self { block_id: block_id.to_owned(), - inserted_rows: vec![], - deleted_rows: vec![], updated_rows, + ..Default::default() } } } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index 31e0632370..a905a9640b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -1,5 +1,5 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; -use crate::entities::{BlockRowInfo, CellChangeset, GridBlockChangeset, GridRowId, InsertedRow, Row, UpdatedRow}; +use crate::entities::{CellChangeset, GridBlockChangeset, InsertedRow, Row, RowInfo, UpdatedRow}; use crate::manager::GridUser; use crate::services::block_revision_editor::GridBlockRevisionEditor; use crate::services::persistence::block_index::BlockIndexCache; @@ -137,14 +137,8 @@ impl GridBlockManager { None => {} Some(row_info) => { let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?; - - let row_identifier = GridRowId { - grid_id: self.grid_id.clone(), - block_id: row_info.block_id, - row_id: row_info.row_id, - }; let _ = self - .notify_did_update_block(&block_id, GridBlockChangeset::delete(&block_id, vec![row_identifier])) + .notify_did_update_block(&block_id, GridBlockChangeset::delete(&block_id, vec![row_info.row_id])) .await?; } } @@ -154,7 +148,7 @@ impl GridBlockManager { pub(crate) async fn delete_rows( &self, - row_orders: Vec, + row_orders: Vec, ) -> FlowyResult> { let mut changesets = vec![]; for grid_block in block_from_row_orders(row_orders) { @@ -186,16 +180,11 @@ impl GridBlockManager { height: row_rev.height, }; - let deleted_row = GridRowId { - grid_id: self.grid_id.clone(), - block_id: row_rev.block_id.clone(), - row_id: row_rev.id.clone(), - }; let notified_changeset = GridBlockChangeset { block_id: editor.block_id.clone(), inserted_rows: vec![insert_row], - deleted_rows: vec![deleted_row], - updated_rows: vec![], + deleted_rows: vec![row_rev.id.clone()], + ..Default::default() }; let _ = self @@ -228,7 +217,7 @@ impl GridBlockManager { } } - pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult> { + pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult> { let editor = self.get_editor(block_id).await?; editor.get_row_infos::<&str>(None).await } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs index 6506b0a367..e73a66c0fa 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs @@ -1,4 +1,4 @@ -use crate::entities::BlockRowInfo; +use crate::entities::RowInfo; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision}; @@ -123,12 +123,12 @@ impl GridBlockRevisionEditor { Ok(cell_revs) } - pub async fn get_row_info(&self, row_id: &str) -> FlowyResult> { + pub async fn get_row_info(&self, row_id: &str) -> FlowyResult> { let row_ids = Some(vec![Cow::Borrowed(row_id)]); Ok(self.get_row_infos(row_ids).await?.pop()) } - pub async fn get_row_infos(&self, row_ids: Option>>) -> FlowyResult> + pub async fn get_row_infos(&self, row_ids: Option>>) -> FlowyResult> where T: AsRef + ToOwned + ?Sized, { @@ -138,8 +138,8 @@ impl GridBlockRevisionEditor { .await .get_row_revs(row_ids)? .iter() - .map(BlockRowInfo::from) - .collect::>(); + .map(RowInfo::from) + .collect::>(); Ok(row_infos) } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 807f3d1fb7..76b68c2fb2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -62,7 +62,10 @@ impl CellDataOperation for CheckboxTypeOption { Ok(DecodedCellData::default()) } - fn apply_filter(&self, _filter: GridCheckboxFilter) -> bool { + fn apply_filter(&self, encoded_data: T, _filter: &GridCheckboxFilter) -> bool + where + T: Into, + { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index a0bfd33cd2..70c8fe98d6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -137,8 +137,10 @@ impl CellDataOperation for DateTypeOption { let date = self.today_desc_from_timestamp(timestamp); DecodedCellData::try_from_bytes(date) } - - fn apply_filter(&self, _filter: GridDateFilter) -> bool { + fn apply_filter(&self, encoded_data: T, _filter: &GridDateFilter) -> bool + where + T: Into, + { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs index f912879ad9..162794d461 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs @@ -178,8 +178,10 @@ impl CellDataOperation for NumberTypeOption { } } } - - fn apply_filter(&self, _filter: GridNumberFilter) -> bool { + fn apply_filter(&self, encoded_data: T, _filter: &GridNumberFilter) -> bool + where + T: Into, + { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index f4e0bd24e2..1d83d438d4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -123,7 +123,10 @@ impl CellDataOperation for SingleSelectTypeOptio DecodedCellData::try_from_bytes(cell_data) } - fn apply_filter(&self, _filter: GridSelectOptionFilter) -> bool { + fn apply_filter(&self, encoded_data: T, _filter: &GridSelectOptionFilter) -> bool + where + T: Into, + { todo!() } @@ -225,7 +228,10 @@ impl CellDataOperation for MultiSelectTypeOption DecodedCellData::try_from_bytes(cell_data) } - fn apply_filter(&self, _filter: GridSelectOptionFilter) -> bool { + fn apply_filter(&self, encoded_data: T, _filter: &GridSelectOptionFilter) -> bool + where + T: Into, + { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 2d9a9d129e..8d1e57bd90 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -52,7 +52,10 @@ impl CellDataOperation for RichTextTypeOption { } } - fn apply_filter(&self, _filter: GridTextFilter) -> bool { + fn apply_filter(&self, encoded_data: T, _filter: &GridTextFilter) -> bool + where + T: Into, + { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option.rs index beb0ce623a..c3741dfdca 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option.rs @@ -50,7 +50,7 @@ impl CellDataOperation, GridTextFilter> for URLType DecodedCellData::try_from_bytes(cell_data) } - fn apply_filter(&self, _filter: GridTextFilter) -> bool { + fn apply_filter(&self, _filter: &GridTextFilter) -> bool { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/filter_cache.rs b/frontend/rust-lib/flowy-grid/src/services/filter/filter_cache.rs new file mode 100644 index 0000000000..3860db128e --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/filter/filter_cache.rs @@ -0,0 +1,163 @@ +use crate::entities::{ + FieldType, GridBlockChangeset, GridCheckboxFilter, GridDateFilter, GridNumberFilter, GridRowId, + GridSelectOptionFilter, GridTextFilter, InsertedRow, +}; + +use dashmap::DashMap; + +use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use flowy_sync::client_grid::GridRevisionPad; + +use std::collections::HashMap; +use std::sync::Arc; +use tokio::sync::RwLock; + +#[derive(Default)] +pub(crate) struct FilterResultCache { + // key: row id + inner: DashMap, +} + +impl FilterResultCache { + pub fn new() -> Arc { + let this = Self::default(); + Arc::new(this) + } +} + +impl std::ops::Deref for FilterResultCache { + type Target = DashMap; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[derive(Default)] +pub(crate) struct FilterResult { + pub(crate) row_id: String, + pub(crate) row_index: i32, + pub(crate) cell_by_field_id: HashMap, +} + +impl FilterResult { + pub(crate) fn new(index: i32, row_rev: &RowRevision) -> Self { + Self { + row_index: index, + row_id: row_rev.id.clone(), + cell_by_field_id: row_rev.cells.iter().map(|(k, _)| (k.clone(), true)).collect(), + } + } + + #[allow(dead_code)] + fn update_cell(&mut self, cell_id: &str, exist: bool) { + self.cell_by_field_id.insert(cell_id.to_owned(), exist); + } + + pub(crate) fn is_visible(&self) -> bool { + todo!() + } +} + +#[derive(Default)] +pub(crate) struct FilterCache { + pub(crate) text_filter: DashMap, + pub(crate) url_filter: DashMap, + pub(crate) number_filter: DashMap, + pub(crate) date_filter: DashMap, + pub(crate) select_option_filter: DashMap, + pub(crate) checkbox_filter: DashMap, +} + +impl FilterCache { + pub(crate) async fn from_grid_pad(grid_pad: &Arc>) -> Arc { + let this = Arc::new(Self::default()); + let _ = reload_filter_cache(this.clone(), None, grid_pad).await; + this + } + + pub(crate) fn remove(&self, filter_id: &FilterId) { + let _ = match filter_id.field_type { + FieldType::RichText => { + let _ = self.text_filter.remove(filter_id); + } + FieldType::Number => { + let _ = self.number_filter.remove(filter_id); + } + FieldType::DateTime => { + let _ = self.date_filter.remove(filter_id); + } + FieldType::SingleSelect => { + let _ = self.select_option_filter.remove(filter_id); + } + FieldType::MultiSelect => { + let _ = self.select_option_filter.remove(filter_id); + } + FieldType::Checkbox => { + let _ = self.checkbox_filter.remove(filter_id); + } + FieldType::URL => { + let _ = self.url_filter.remove(filter_id); + } + }; + } +} + +pub(crate) async fn reload_filter_cache( + cache: Arc, + field_ids: Option>, + grid_pad: &Arc>, +) { + let grid_pad = grid_pad.read().await; + let filters_revs = grid_pad.get_filters(None, field_ids).unwrap_or_default(); + + for filter_rev in filters_revs { + match grid_pad.get_field_rev(&filter_rev.field_id) { + None => {} + Some((_, field_rev)) => { + let filter_id = FilterId::from(field_rev); + let field_type: FieldType = field_rev.field_type_rev.into(); + match &field_type { + FieldType::RichText => { + let _ = cache.text_filter.insert(filter_id, GridTextFilter::from(filter_rev)); + } + FieldType::Number => { + let _ = cache + .number_filter + .insert(filter_id, GridNumberFilter::from(filter_rev)); + } + FieldType::DateTime => { + let _ = cache.date_filter.insert(filter_id, GridDateFilter::from(filter_rev)); + } + FieldType::SingleSelect | FieldType::MultiSelect => { + let _ = cache + .select_option_filter + .insert(filter_id, GridSelectOptionFilter::from(filter_rev)); + } + FieldType::Checkbox => { + let _ = cache + .checkbox_filter + .insert(filter_id, GridCheckboxFilter::from(filter_rev)); + } + FieldType::URL => { + let _ = cache.url_filter.insert(filter_id, GridTextFilter::from(filter_rev)); + } + } + } + } + } +} +#[derive(Hash, Eq, PartialEq)] +pub(crate) struct FilterId { + pub(crate) field_id: String, + pub(crate) field_type: FieldType, +} + +impl std::convert::From<&Arc> for FilterId { + fn from(rev: &Arc) -> Self { + Self { + field_id: rev.id.clone(), + field_type: rev.field_type_rev.into(), + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs b/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs index 28a5bae255..c328e14965 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs @@ -1,16 +1,20 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; -use crate::entities::{ - FieldType, GridBlockChangeset, GridCheckboxFilter, GridDateFilter, GridNumberFilter, GridRowId, - GridSelectOptionFilter, GridTextFilter, InsertedRow, -}; +use crate::entities::{FieldType, GridBlockChangeset, GridTextFilter}; use crate::services::block_manager::GridBlockManager; +use crate::services::field::RichTextTypeOption; +use crate::services::filter::filter_cache::{ + reload_filter_cache, FilterCache, FilterId, FilterResult, FilterResultCache, +}; use crate::services::grid_editor_task::GridServiceTaskScheduler; -use crate::services::row::GridBlockSnapshot; +use crate::services::row::{CellDataOperation, GridBlockSnapshot}; use crate::services::tasks::{FilterTaskContext, Task, TaskContent}; +use dashmap::mapref::one::{Ref, RefMut}; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{CellRevision, FieldId, FieldRevision, RowRevision}; use flowy_sync::client_grid::GridRevisionPad; use flowy_sync::entities::grid::GridSettingChangesetParams; +use rayon::prelude::*; +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; @@ -21,8 +25,8 @@ pub(crate) struct GridFilterService { scheduler: Arc, grid_pad: Arc>, block_manager: Arc, - filter_cache: Arc>, - filter_result_cache: Arc>, + filter_cache: Arc, + filter_result_cache: Arc, } impl GridFilterService { pub async fn new( @@ -31,13 +35,14 @@ impl GridFilterService { scheduler: S, ) -> Self { let grid_id = grid_pad.read().await.grid_id(); - let filter_cache = Arc::new(RwLock::new(FilterCache::from_grid_pad(&grid_pad).await)); - let filter_result_cache = Arc::new(RwLock::new(FilterResultCache::default())); + let scheduler = Arc::new(scheduler); + let filter_cache = FilterCache::from_grid_pad(&grid_pad).await; + let filter_result_cache = FilterResultCache::new(); Self { grid_id, grid_pad, block_manager, - scheduler: Arc::new(scheduler), + scheduler, filter_cache, filter_result_cache, } @@ -55,37 +60,31 @@ impl GridFilterService { let mut changesets = vec![]; for (index, block) in task_context.blocks.into_iter().enumerate() { - let mut inserted_rows = vec![]; - let mut deleted_rows = vec![]; - block.row_revs.iter().for_each(|row_rev| { - let result = filter_row( - index, - row_rev, - &self.filter_cache, - &self.filter_result_cache, - &field_revs, - ); + let results = block + .row_revs + .par_iter() + .map(|row_rev| { + let filter_result_cache = self.filter_result_cache.clone(); + let filter_cache = self.filter_cache.clone(); + filter_row(index, row_rev, filter_cache, filter_result_cache, &field_revs) + }) + .collect::>(); + + let mut visible_rows = vec![]; + let mut hide_rows = vec![]; + for result in results { if result.is_visible() { - inserted_rows.push(InsertedRow { - row_id: Default::default(), - block_id: Default::default(), - height: 1, - index: Some(result.row_index), - }); + visible_rows.push(result.row_id); } else { - deleted_rows.push(GridRowId { - grid_id: self.grid_id.clone(), - block_id: block.block_id.clone(), - row_id: result.row_id, - }); + hide_rows.push(result.row_id); } - }); + } let changeset = GridBlockChangeset { block_id: block.block_id, - inserted_rows, - deleted_rows, - updated_rows: vec![], + hide_rows, + visible_rows, + ..Default::default() }; changesets.push(changeset); } @@ -99,13 +98,13 @@ impl GridFilterService { } if let Some(filter_id) = &changeset.insert_filter { - let mut cache = self.filter_cache.write().await; let field_ids = Some(vec![filter_id.field_id.clone()]); - reload_filter_cache(&mut cache, field_ids, &self.grid_pad).await; + reload_filter_cache(self.filter_cache.clone(), field_ids, &self.grid_pad).await; + todo!() } if let Some(filter_id) = &changeset.delete_filter { - self.filter_cache.write().await.remove(filter_id); + self.filter_cache.remove(filter_id); } if let Ok(blocks) = self.block_manager.get_block_snapshots(None).await { @@ -138,15 +137,58 @@ impl GridFilterService { fn filter_row( index: usize, row_rev: &Arc, - _filter_cache: &Arc>, - _filter_result_cache: &Arc>, - _field_revs: &HashMap>, + filter_cache: Arc, + filter_result_cache: Arc, + field_revs: &HashMap>, ) -> FilterResult { - let filter_result = FilterResult::new(index as i32, row_rev); - row_rev.cells.iter().for_each(|(_k, cell_rev)| { - let _cell_rev: &CellRevision = cell_rev; - }); - filter_result + match filter_result_cache.get_mut(&row_rev.id) { + None => { + let mut filter_result = FilterResult::new(index as i32, row_rev); + for (field_id, cell_rev) in row_rev.cells.iter() { + let _ = update_filter_result(field_revs, &mut filter_result, &filter_cache, field_id, cell_rev); + } + filter_result_cache.insert(row_rev.id.clone(), filter_result); + } + Some(mut result) => { + for (field_id, cell_rev) in row_rev.cells.iter() { + let _ = update_filter_result(field_revs, result.value_mut(), &filter_cache, field_id, cell_rev); + } + } + } + + todo!() +} + +fn update_filter_result( + field_revs: &HashMap>, + filter_result: &mut FilterResult, + filter_cache: &Arc, + field_id: &str, + cell_rev: &CellRevision, +) -> Option<()> { + let field_rev = field_revs.get(field_id)?; + let field_type = FieldType::from(field_rev.field_type_rev); + let filter_id = FilterId { + field_id: field_id.to_owned(), + field_type, + }; + match &filter_id.field_type { + FieldType::RichText => match filter_cache.text_filter.get(&filter_id) { + None => {} + Some(filter) => { + // let v = field_rev + // .get_type_option_entry::(&filter_id.field_type)? + // .apply_filter(cell_rev, &filter); + } + }, + FieldType::Number => {} + FieldType::DateTime => {} + FieldType::SingleSelect => {} + FieldType::MultiSelect => {} + FieldType::Checkbox => {} + FieldType::URL => {} + } + None } pub struct GridFilterChangeset { @@ -177,145 +219,3 @@ impl std::convert::From<&GridSettingChangesetParams> for GridFilterChangeset { } } } - -#[derive(Default)] -struct FilterResultCache { - #[allow(dead_code)] - rows: HashMap, -} - -impl FilterResultCache { - #[allow(dead_code)] - fn insert(&mut self, row_id: &str, result: FilterResult) { - self.rows.insert(row_id.to_owned(), result); - } -} - -#[derive(Default)] -struct FilterResult { - row_id: String, - row_index: i32, - cell_by_field_id: HashMap, -} - -impl FilterResult { - fn new(index: i32, row_rev: &RowRevision) -> Self { - Self { - row_index: index, - row_id: row_rev.id.clone(), - cell_by_field_id: row_rev.cells.iter().map(|(k, _)| (k.clone(), true)).collect(), - } - } - - #[allow(dead_code)] - fn update_cell(&mut self, cell_id: &str, exist: bool) { - self.cell_by_field_id.insert(cell_id.to_owned(), exist); - } - - fn is_visible(&self) -> bool { - todo!() - } -} - -#[derive(Default)] -struct FilterCache { - text_filter: HashMap, - url_filter: HashMap, - number_filter: HashMap, - date_filter: HashMap, - select_option_filter: HashMap, - checkbox_filter: HashMap, -} - -impl FilterCache { - async fn from_grid_pad(grid_pad: &Arc>) -> Self { - let mut this = Self::default(); - let _ = reload_filter_cache(&mut this, None, grid_pad).await; - this - } - - fn remove(&mut self, filter_id: &FilterId) { - let _ = match filter_id.field_type { - FieldType::RichText => { - let _ = self.text_filter.remove(filter_id); - } - FieldType::Number => { - let _ = self.number_filter.remove(filter_id); - } - FieldType::DateTime => { - let _ = self.date_filter.remove(filter_id); - } - FieldType::SingleSelect => { - let _ = self.select_option_filter.remove(filter_id); - } - FieldType::MultiSelect => { - let _ = self.select_option_filter.remove(filter_id); - } - FieldType::Checkbox => { - let _ = self.checkbox_filter.remove(filter_id); - } - FieldType::URL => { - let _ = self.url_filter.remove(filter_id); - } - }; - } -} - -async fn reload_filter_cache( - cache: &mut FilterCache, - field_ids: Option>, - grid_pad: &Arc>, -) { - let grid_pad = grid_pad.read().await; - let filters_revs = grid_pad.get_filters(None, field_ids).unwrap_or_default(); - - for filter_rev in filters_revs { - match grid_pad.get_field_rev(&filter_rev.field_id) { - None => {} - Some((_, field_rev)) => { - let filter_id = FilterId::from(field_rev); - let field_type: FieldType = field_rev.field_type_rev.into(); - match &field_type { - FieldType::RichText => { - let _ = cache.text_filter.insert(filter_id, GridTextFilter::from(filter_rev)); - } - FieldType::Number => { - let _ = cache - .number_filter - .insert(filter_id, GridNumberFilter::from(filter_rev)); - } - FieldType::DateTime => { - let _ = cache.date_filter.insert(filter_id, GridDateFilter::from(filter_rev)); - } - FieldType::SingleSelect | FieldType::MultiSelect => { - let _ = cache - .select_option_filter - .insert(filter_id, GridSelectOptionFilter::from(filter_rev)); - } - FieldType::Checkbox => { - let _ = cache - .checkbox_filter - .insert(filter_id, GridCheckboxFilter::from(filter_rev)); - } - FieldType::URL => { - let _ = cache.url_filter.insert(filter_id, GridTextFilter::from(filter_rev)); - } - } - } - } - } -} -#[derive(Hash, Eq, PartialEq)] -struct FilterId { - field_id: String, - field_type: FieldType, -} - -impl std::convert::From<&Arc> for FilterId { - fn from(rev: &Arc) -> Self { - Self { - field_id: rev.id.clone(), - field_type: rev.field_type_rev.into(), - } - } -} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs b/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs index 647885e527..39ae6ba462 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs @@ -1,3 +1,4 @@ +mod filter_cache; mod filter_service; pub(crate) use filter_service::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index d973b8a190..5d478b3bd2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -265,14 +265,14 @@ impl GridRevisionEditor { Ok(()) } - pub async fn create_row(&self, start_row_id: Option) -> FlowyResult { + pub async fn create_row(&self, start_row_id: Option) -> FlowyResult { let field_revs = self.grid_pad.read().await.get_field_revs(None)?; let block_id = self.block_id().await?; // insert empty row below the row whose id is upper_row_id let row_rev_ctx = CreateRowRevisionBuilder::new(&field_revs).build(); let row_rev = make_row_rev_from_context(&block_id, row_rev_ctx); - let row_order = BlockRowInfo::from(&row_rev); + let row_order = RowInfo::from(&row_rev); // insert the row let row_count = self.block_manager.create_row(&block_id, row_rev, start_row_id).await?; @@ -283,13 +283,13 @@ impl GridRevisionEditor { Ok(row_order) } - pub async fn insert_rows(&self, contexts: Vec) -> FlowyResult> { + pub async fn insert_rows(&self, contexts: Vec) -> FlowyResult> { let block_id = self.block_id().await?; let mut rows_by_block_id: HashMap> = HashMap::new(); let mut row_orders = vec![]; for ctx in contexts { let row_rev = make_row_rev_from_context(&block_id, ctx); - row_orders.push(BlockRowInfo::from(&row_rev)); + row_orders.push(RowInfo::from(&row_rev)); rows_by_block_id .entry(block_id.clone()) .or_insert_with(Vec::new) @@ -421,7 +421,7 @@ impl GridRevisionEditor { Ok(block_meta_revs) } - pub async fn delete_rows(&self, row_orders: Vec) -> FlowyResult<()> { + pub async fn delete_rows(&self, row_orders: Vec) -> FlowyResult<()> { let changesets = self.block_manager.delete_rows(row_orders).await?; for changeset in changesets { let _ = self.update_block(changeset).await?; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs index 99787f8550..5c346c5be0 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs @@ -17,7 +17,9 @@ pub trait CellDataOperation { where T: Into; - fn apply_filter(&self, filter: F) -> bool; + fn apply_filter(&self, encoded_data: T, filter: &F) -> bool + where + T: Into; fn apply_changeset>( &self, @@ -73,6 +75,13 @@ impl std::convert::TryInto for String { } } +impl std::convert::TryFrom<&CellRevision> for TypeOptionCellData { + type Error = FlowyError; + + fn try_from(value: &CellRevision) -> Result { + Self::from_str(&value.data) + } +} impl TypeOptionCellData { pub fn new(data: T, field_type: FieldType) -> Self { TypeOptionCellData { diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index 96da30e574..1b9ce80101 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -1,4 +1,4 @@ -use crate::entities::{BlockRowInfo, GridBlock, RepeatedGridBlock, Row}; +use crate::entities::{GridBlock, RepeatedGridBlock, Row, RowInfo}; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use std::collections::HashMap; @@ -9,7 +9,7 @@ pub struct GridBlockSnapshot { pub row_revs: Vec>, } -pub(crate) fn block_from_row_orders(row_orders: Vec) -> Vec { +pub(crate) fn block_from_row_orders(row_orders: Vec) -> Vec { let mut map: HashMap = HashMap::new(); row_orders.into_iter().for_each(|row_info| { // Memory Optimization: escape clone block_id @@ -35,8 +35,8 @@ pub(crate) fn block_from_row_orders(row_orders: Vec) -> Vec]) -> Vec { - row_revs.iter().map(BlockRowInfo::from).collect::>() +pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc]) -> Vec { + row_revs.iter().map(RowInfo::from).collect::>() } pub(crate) fn make_row_from_row_rev(fields: &[Arc], row_rev: Arc) -> Option { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs index f833dff8a6..a2ab3ec2f4 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs @@ -137,9 +137,9 @@ async fn grid_row_add_date_cell_test() { } let context = builder.build(); let date_field = date_field.unwrap(); - let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone(); + let cell_rev = context.cell_by_field_id.get(&date_field.id).unwrap().clone(); assert_eq!( - decode_cell_data(cell_data.data.clone(), &date_field) + decode_cell_data(cell_rev, &date_field) .parse::() .unwrap() .date, diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 0ca04024a6..e6c8b901a5 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -99,7 +99,7 @@ pub struct GridEditorTest { pub row_revs: Vec>, pub field_count: usize, - pub row_order_by_row_id: HashMap, + pub row_order_by_row_id: HashMap, } impl GridEditorTest { @@ -220,7 +220,7 @@ impl GridEditorTest { let row_orders = row_ids .into_iter() .map(|row_id| self.row_order_by_row_id.get(&row_id).unwrap().clone()) - .collect::>(); + .collect::>(); self.editor.delete_rows(row_orders).await.unwrap(); self.row_revs = self.get_row_revs().await;