diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 53660bdea2..e15c113484 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,5 +1,5 @@ use crate::manager::GridManager; -use crate::services::field::{type_option_builder_from_json_str, SelectOption}; +use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str, SelectOption}; use crate::services::grid_editor::ClientGridEditor; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; @@ -85,7 +85,19 @@ pub(crate) async fn switch_to_field_handler( ) -> DataResult { let params: EditFieldParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let edit_context = editor.switch_to_field_type(¶ms.field_id, params.field_type).await?; + editor + .switch_to_field_type(¶ms.field_id, ¶ms.field_type) + .await?; + + let field_meta = editor.get_field(¶ms.field_id).await?; + let edit_context = make_field_edit_context( + ¶ms.grid_id, + Some(params.field_id), + params.field_type, + editor, + field_meta, + ) + .await?; data_result(edit_context) } @@ -115,31 +127,46 @@ pub(crate) async fn get_field_context_handler( ) -> DataResult { let params = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - let mut field_meta = get_or_create_field_meta(¶ms, editor).await?; - let s = field_meta.get_type_option_str().unwrap(); - let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); - let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let edit_context = + make_field_edit_context(¶ms.grid_id, params.field_id, params.field_type, editor, None).await?; - let field: Field = field_meta.into(); - let edit_context = EditFieldContext { - grid_id: params.grid_id, - grid_field: field, - type_option_data, - }; data_result(edit_context) } +async fn make_field_edit_context( + grid_id: &str, + field_id: Option, + field_type: FieldType, + editor: Arc, + field_meta: Option, +) -> FlowyResult { + let field_meta = field_meta.unwrap_or(get_or_create_field_meta(field_id, &field_type, editor).await?); + let s = field_meta + .get_type_option_str() + .unwrap_or_else(|| default_type_option_builder_from_type(&field_type).entry().json_str()); + + let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); + let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let field: Field = field_meta.into(); + Ok(EditFieldContext { + grid_id: grid_id.to_string(), + grid_field: field, + type_option_data, + }) +} + async fn get_or_create_field_meta( - params: &GetEditFieldContextPayload, + field_id: Option, + field_type: &FieldType, editor: Arc, ) -> FlowyResult { - if params.field_id.is_some() { - if let Some(field_meta) = editor.get_field(params.field_id.as_ref().unwrap()).await? { + if field_id.is_some() { + if let Some(field_meta) = editor.get_field(field_id.as_ref().unwrap()).await? { return Ok(field_meta); } } - editor.default_field_meta(¶ms.field_type).await + editor.create_next_field_meta(field_type).await } #[tracing::instrument(level = "debug", skip(data, manager), err)] 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 226949a5d2..3ca651f5dc 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,10 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{type_option_builder_from_bytes, FieldBuilder}; +use crate::services::field::{ + default_type_option_builder_from_type, type_option_builder_from_bytes, type_option_builder_from_json_str, + FieldBuilder, +}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; @@ -85,7 +88,7 @@ impl ClientGridEditor { Ok(()) } - pub async fn default_field_meta(&self, field_type: &FieldType) -> FlowyResult { + pub async fn create_next_field_meta(&self, field_type: &FieldType) -> FlowyResult { let name = format!("Property {}", self.pad.read().await.fields().len() + 1); let field_meta = FieldBuilder::from_field_type(field_type).name(&name).build(); Ok(field_meta) @@ -95,7 +98,7 @@ impl ClientGridEditor { self.pad.read().await.contain_field(field_id) } - pub async fn update_field(&self, mut params: FieldChangesetParams) -> FlowyResult<()> { + pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { let deserializer = match self.pad.read().await.get_field(¶ms.field_id) { None => return Err(ErrorCode::FieldDoesNotExist.into()), Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), @@ -112,10 +115,15 @@ impl ClientGridEditor { Ok(()) } - pub async fn switch_to_field_type(&self, field_id: &str, field_type: FieldType) -> FlowyResult { - let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?; + pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> { + let type_option_json_builder = + |field_type: &FieldType| -> String { default_type_option_builder_from_type(field_type).entry().json_str() }; + + let _ = self + .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?)) + .await?; let _ = self.notify_did_update_fields().await?; - todo!() + Ok(()) } pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 5d7085e92c..eac4b97be9 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -3,7 +3,8 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; use bytes::Bytes; use flowy_grid_data_model::entities::{ - FieldChangesetParams, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder, + FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta, GridBlockMetaChangeset, GridMeta, + RepeatedFieldOrder, TypeOptionDataEntry, }; use lib_infra::uuid; @@ -89,6 +90,37 @@ impl GridMetaPad { }) } + pub fn switch_to_field( + &mut self, + field_id: &str, + field_type: FieldType, + type_option_json_builder: B, + ) -> CollaborateResult> + where + B: FnOnce(&FieldType) -> String, + { + self.modify_grid(|grid| { + // + match grid.fields.iter_mut().find(|field_meta| field_meta.id == field_id) { + None => { + tracing::warn!("Can not find the field with id: {}", field_id); + Ok(None) + } + Some(field_meta) => { + if field_meta.get_type_option_str().is_none() { + let type_option_json = type_option_json_builder(&field_type); + field_meta + .type_option_by_field_type_id + .insert(&field_type, type_option_json); + } + + field_meta.field_type = field_type; + Ok(Some(())) + } + } + }) + } + pub fn update_field( &mut self, changeset: FieldChangesetParams,