From 155cf3dca5a14b623b4d32644341753eccd9bb1c Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 27 Sep 2022 17:26:22 +0800 Subject: [PATCH] fix: display cell data after switching to text field --- .../widgets/cell/url_cell/url_cell.dart | 13 ++-- .../flowy-grid/src/entities/cell_entities.rs | 9 ++- .../src/services/cell/cell_operation.rs | 65 +++++++++++++++++-- .../checkbox_type_option.rs | 10 +++ .../date_type_option/date_type_option.rs | 11 ++++ .../number_type_option/number_type_option.rs | 37 ++++++++--- .../selection_type_option/select_option.rs | 15 +++++ .../text_type_option/text_tests.rs | 12 ++-- .../text_type_option/text_type_option.rs | 32 ++++++++- .../url_type_option/url_type_option.rs | 10 +++ .../flowy-grid/src/services/grid_editor.rs | 10 ++- .../src/services/group/controller.rs | 8 +-- 12 files changed, 193 insertions(+), 39 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart index 5ed184aafb..04d10f9aa2 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart @@ -97,7 +97,6 @@ class GridURLCell extends GridCellWidget { class _GridURLCellState extends GridCellState { final _popoverController = PopoverController(); - GridURLCellController? _cellContext; late URLCellBloc _cellBloc; @override @@ -132,6 +131,7 @@ class _GridURLCellState extends GridCellState { controller: _popoverController, constraints: BoxConstraints.loose(const Size(300, 160)), direction: PopoverDirection.bottomWithLeftAligned, + triggerActions: PopoverTriggerFlags.none, offset: const Offset(0, 20), child: SizedBox.expand( child: GestureDetector( @@ -144,7 +144,8 @@ class _GridURLCellState extends GridCellState { ), popupBuilder: (BuildContext popoverContext) { return URLEditorPopover( - cellController: _cellContext!, + cellController: widget.cellControllerBuilder.build() + as GridURLCellController, ); }, onClose: () { @@ -166,17 +167,13 @@ class _GridURLCellState extends GridCellState { final uri = Uri.parse(url); if (url.isNotEmpty && await canLaunchUrl(uri)) { await launchUrl(uri); - } else { - _cellContext = - widget.cellControllerBuilder.build() as GridURLCellController; - widget.onCellEditing.value = true; - _popoverController.show(); } } @override void requestBeginFocus() { - _openUrlOrEdit(_cellBloc.state.url); + widget.onCellEditing.value = true; + _popoverController.show(); } @override diff --git a/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs index 3493f0940c..48886f1918 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs @@ -1,3 +1,4 @@ +use crate::entities::FieldType; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; @@ -74,15 +75,20 @@ pub struct GridCellPB { #[pb(index = 1)] pub field_id: String, + // The data was encoded in field_type's data type #[pb(index = 2)] pub data: Vec, + + #[pb(index = 3, one_of)] + pub field_type: Option, } impl GridCellPB { - pub fn new(field_id: &str, data: Vec) -> Self { + pub fn new(field_id: &str, field_type: FieldType, data: Vec) -> Self { Self { field_id: field_id.to_owned(), data, + field_type: Some(field_type), } } @@ -90,6 +96,7 @@ impl GridCellPB { Self { field_id: field_id.to_owned(), data: vec![], + field_type: None, } } } diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs b/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs index 0c657b8fd1..43b2eb420d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs @@ -24,6 +24,13 @@ pub trait CellDisplayable { decoded_field_type: &FieldType, field_rev: &FieldRevision, ) -> FlowyResult; + + fn display_string( + &self, + cell_data: CellData, + decoded_field_type: &FieldType, + field_rev: &FieldRevision, + ) -> FlowyResult; } // CD: Short for CellData. This type is the type return by apply_changeset function. @@ -84,16 +91,16 @@ pub fn apply_cell_data_changeset>( pub fn decode_any_cell_data + Debug>( data: T, field_rev: &FieldRevision, -) -> CellBytes { +) -> (FieldType, CellBytes) { + let to_field_type = field_rev.ty.into(); match data.try_into() { Ok(any_cell_data) => { let AnyCellData { data, field_type } = any_cell_data; - let to_field_type = field_rev.ty.into(); match try_decode_cell_data(data.into(), &field_type, &to_field_type, field_rev) { - Ok(cell_bytes) => cell_bytes, + Ok(cell_bytes) => (field_type, cell_bytes), Err(e) => { tracing::error!("Decode cell data failed, {:?}", e); - CellBytes::default() + (field_type, CellBytes::default()) } } } @@ -101,12 +108,58 @@ pub fn decode_any_cell_data + Debug> // It's okay to ignore this error, because it's okay that the current cell can't // display the existing cell data. For example, the UI of the text cell will be blank if // the type of the data of cell is Number. - CellBytes::default() + + (to_field_type, CellBytes::default()) } } } -/// Use the `to_field_type`'s TypeOption to parse the cell data into `from_field_type`'s data. +pub fn decode_cell_data_to_string( + cell_data: CellData, + from_field_type: &FieldType, + to_field_type: &FieldType, + field_rev: &FieldRevision, +) -> FlowyResult { + let cell_data = cell_data.try_into_inner()?; + let get_cell_display_str = || { + let field_type: FieldTypeRevision = to_field_type.into(); + let result = match to_field_type { + FieldType::RichText => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + FieldType::Number => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + FieldType::DateTime => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + FieldType::SingleSelect => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + FieldType::MultiSelect => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + FieldType::Checkbox => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + FieldType::URL => field_rev + .get_type_option::(field_type)? + .display_string(cell_data.into(), from_field_type, field_rev), + }; + Some(result) + }; + + match get_cell_display_str() { + Some(Ok(s)) => Ok(s), + Some(Err(err)) => { + tracing::error!("{:?}", err); + Ok("".to_owned()) + } + None => Ok("".to_owned()), + } +} + +/// Use the `to_field_type`'s TypeOption to parse the cell data into `from_field_type` type's data. /// /// Each `FieldType` has its corresponding `TypeOption` that implements the `CellDisplayable` /// and `CellDataOperation` traits. diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs index fbb1ba64e8..e6d7b39d48 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs @@ -48,6 +48,16 @@ impl CellDisplayable for CheckboxTypeOptionPB { let cell_data = cell_data.try_into_inner()?; Ok(CellBytes::new(cell_data)) } + + fn display_string( + &self, + cell_data: CellData, + _decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + let cell_data = cell_data.try_into_inner()?; + Ok(cell_data.to_string()) + } } impl CellDataOperation for CheckboxTypeOptionPB { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs index e79ae3574c..f883790524 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs @@ -127,6 +127,17 @@ impl CellDisplayable for DateTypeOptionPB { let date_cell_data = self.today_desc_from_timestamp(timestamp); CellBytes::from(date_cell_data) } + + fn display_string( + &self, + cell_data: CellData, + _decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + let timestamp = cell_data.try_into_inner()?; + let date_cell_data = self.today_desc_from_timestamp(timestamp); + Ok(date_cell_data.date) + } } impl CellDataOperation for DateTypeOptionPB { 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 984e7561bc..d35e812d77 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 @@ -1,6 +1,6 @@ use crate::entities::FieldType; use crate::impl_type_option; -use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation}; +use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable}; use crate::services::field::type_options::number_type_option::format::*; use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBuilder}; use bytes::Bytes; @@ -102,17 +102,13 @@ pub(crate) fn strip_currency_symbol(s: T) -> String { s } -impl CellDataOperation for NumberTypeOptionPB { - fn decode_cell_data( +impl CellDisplayable for NumberTypeOptionPB { + fn display_data( &self, cell_data: CellData, - decoded_field_type: &FieldType, + _decoded_field_type: &FieldType, _field_rev: &FieldRevision, ) -> FlowyResult { - if decoded_field_type.is_date() { - return Ok(CellBytes::default()); - } - let cell_data: String = cell_data.try_into_inner()?; match self.format_cell_data(&cell_data) { Ok(num) => Ok(CellBytes::new(num.to_string())), @@ -120,6 +116,31 @@ impl CellDataOperation for NumberTypeOptionPB { } } + fn display_string( + &self, + cell_data: CellData, + _decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + let cell_data: String = cell_data.try_into_inner()?; + Ok(cell_data) + } +} + +impl CellDataOperation for NumberTypeOptionPB { + fn decode_cell_data( + &self, + cell_data: CellData, + decoded_field_type: &FieldType, + field_rev: &FieldRevision, + ) -> FlowyResult { + if decoded_field_type.is_date() { + return Ok(CellBytes::default()); + } + + self.display_data(cell_data, decoded_field_type, field_rev) + } + fn apply_changeset( &self, changeset: CellDataChangeset, diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs index ff579f8172..7d40903fe8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs @@ -120,6 +120,21 @@ where ) -> FlowyResult { CellBytes::from(self.selected_select_option(cell_data)) } + + fn display_string( + &self, + cell_data: CellData, + _decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + Ok(self + .selected_select_option(cell_data) + .select_options + .into_iter() + .map(|option| option.name) + .collect::>() + .join(SELECTION_IDS_SEPARATOR)) + } } pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult> { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs index 6e0073a0d0..2f2a5ed188 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs @@ -17,10 +17,10 @@ mod tests { type_option .decode_cell_data(1647251762.into(), &field_type, &field_rev) .unwrap() - .parser::() + .parser::() .unwrap() - .date, - "Mar 14,2022".to_owned() + .as_ref(), + "Mar 14,2022" ); } @@ -40,10 +40,10 @@ mod tests { type_option .decode_cell_data(option_id.into(), &field_type, &field_rev) .unwrap() - .parser::() + .parser::() .unwrap() - .select_options, - vec![done_option], + .to_string(), + done_option.name, ); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs index 6636d2bcc7..ab33c1345b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs @@ -1,8 +1,8 @@ use crate::entities::FieldType; use crate::impl_type_option; use crate::services::cell::{ - try_decode_cell_data, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation, CellDisplayable, - FromCellString, + decode_cell_data_to_string, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation, + CellDisplayable, FromCellString, }; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use bytes::Bytes; @@ -44,6 +44,16 @@ impl CellDisplayable for RichTextTypeOptionPB { let cell_str: String = cell_data.try_into_inner()?; Ok(CellBytes::new(cell_str)) } + + fn display_string( + &self, + cell_data: CellData, + _decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + let cell_str: String = cell_data.try_into_inner()?; + Ok(cell_str) + } } impl CellDataOperation for RichTextTypeOptionPB { @@ -57,8 +67,10 @@ impl CellDataOperation for RichTextTypeOptionPB { || decoded_field_type.is_single_select() || decoded_field_type.is_multi_select() || decoded_field_type.is_number() + || decoded_field_type.is_url() { - try_decode_cell_data(cell_data, decoded_field_type, decoded_field_type, field_rev) + let s = decode_cell_data_to_string(cell_data, decoded_field_type, decoded_field_type, field_rev); + Ok(CellBytes::new(s.unwrap_or_else(|_| "".to_owned()))) } else { self.display_data(cell_data, decoded_field_type, field_rev) } @@ -85,6 +97,14 @@ impl AsRef for TextCellData { } } +impl std::ops::Deref for TextCellData { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl FromCellString for TextCellData { fn from_cell_str(s: &str) -> FlowyResult where @@ -94,6 +114,12 @@ impl FromCellString for TextCellData { } } +impl ToString for TextCellData { + fn to_string(&self) -> String { + self.0.clone() + } +} + pub struct TextCellDataParser(); impl CellBytesParser for TextCellDataParser { type Object = TextCellData; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs index d34dfc12d3..5e426f368f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs @@ -42,6 +42,16 @@ impl CellDisplayable for URLTypeOptionPB { let cell_data: URLCellDataPB = cell_data.try_into_inner()?; CellBytes::from(cell_data) } + + fn display_string( + &self, + cell_data: CellData, + _decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + let cell_data: URLCellDataPB = cell_data.try_into_inner()?; + Ok(cell_data.content) + } } impl CellDataOperation for URLTypeOptionPB { 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 ccad53bf5c..41b1ff076f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -435,14 +435,18 @@ impl GridRevisionEditor { } pub async fn get_cell(&self, params: &GridCellIdParams) -> Option { - let cell_bytes = self.get_cell_bytes(params).await?; - Some(GridCellPB::new(¶ms.field_id, cell_bytes.to_vec())) + let (field_type, cell_bytes) = self.decode_any_cell_data(params).await?; + Some(GridCellPB::new(¶ms.field_id, field_type, cell_bytes.to_vec())) } pub async fn get_cell_bytes(&self, params: &GridCellIdParams) -> Option { + let (_, cell_data) = self.decode_any_cell_data(params).await?; + Some(cell_data) + } + + async fn decode_any_cell_data(&self, params: &GridCellIdParams) -> Option<(FieldType, CellBytes)> { let field_rev = self.get_field_rev(¶ms.field_id).await?; let row_rev = self.block_manager.get_row_rev(¶ms.row_id).await.ok()??; - let cell_rev = row_rev.cells.get(¶ms.field_id)?.clone(); Some(decode_any_cell_data(cell_rev.data, &field_rev)) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index f65b87e829..80cfa8edec 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -205,7 +205,7 @@ where if let Some(cell_rev) = cell_rev { let mut grouped_rows: Vec = vec![]; - let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev); + let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev).1; let cell_data = cell_bytes.parser::

()?; for group in self.group_ctx.groups() { if self.can_group(&group.filter_content, &cell_data) { @@ -244,7 +244,7 @@ where field_rev: &FieldRevision, ) -> FlowyResult> { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { - let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_data = cell_bytes.parser::

()?; let mut changesets = self.add_row_if_match(row_rev, &cell_data); let default_group_changeset = self.update_default_group(row_rev, &changesets); @@ -265,7 +265,7 @@ where ) -> FlowyResult> { // if the cell_rev is none, then the row must be crated from the default group. if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { - let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_data = cell_bytes.parser::

()?; Ok(self.remove_row_if_match(row_rev, &cell_data)) } else { @@ -285,7 +285,7 @@ where }; if let Some(cell_rev) = cell_rev { - let cell_bytes = decode_any_cell_data(cell_rev.data, context.field_rev); + let cell_bytes = decode_any_cell_data(cell_rev.data, context.field_rev).1; let cell_data = cell_bytes.parser::

()?; Ok(self.move_row(&cell_data, context)) } else {