Skip to content

Commit fd821b3

Browse files
committed
fix: display cell data after switching to text field
1 parent 76c642a commit fd821b3

File tree

12 files changed

+192
-38
lines changed

12 files changed

+192
-38
lines changed

frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ class GridURLCell extends GridCellWidget {
9797

9898
class _GridURLCellState extends GridCellState<GridURLCell> {
9999
final _popoverController = PopoverController();
100-
GridURLCellController? _cellContext;
101100
late URLCellBloc _cellBloc;
102101

103102
@override
@@ -132,6 +131,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
132131
controller: _popoverController,
133132
constraints: BoxConstraints.loose(const Size(300, 160)),
134133
direction: PopoverDirection.bottomWithLeftAligned,
134+
triggerActions: PopoverTriggerFlags.none,
135135
offset: const Offset(0, 20),
136136
child: SizedBox.expand(
137137
child: GestureDetector(
@@ -144,7 +144,8 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
144144
),
145145
popupBuilder: (BuildContext popoverContext) {
146146
return URLEditorPopover(
147-
cellController: _cellContext!,
147+
cellController: widget.cellControllerBuilder.build()
148+
as GridURLCellController,
148149
);
149150
},
150151
onClose: () {
@@ -166,17 +167,13 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
166167
final uri = Uri.parse(url);
167168
if (url.isNotEmpty && await canLaunchUrl(uri)) {
168169
await launchUrl(uri);
169-
} else {
170-
_cellContext =
171-
widget.cellControllerBuilder.build() as GridURLCellController;
172-
widget.onCellEditing.value = true;
173-
_popoverController.show();
174170
}
175171
}
176172

177173
@override
178174
void requestBeginFocus() {
179-
_openUrlOrEdit(_cellBloc.state.url);
175+
widget.onCellEditing.value = true;
176+
_popoverController.show();
180177
}
181178

182179
@override

frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::entities::FieldType;
12
use flowy_derive::ProtoBuf;
23
use flowy_error::ErrorCode;
34
use flowy_grid_data_model::parser::NotEmptyStr;
@@ -74,22 +75,28 @@ pub struct GridCellPB {
7475
#[pb(index = 1)]
7576
pub field_id: String,
7677

78+
// The data was encoded in field_type's data type
7779
#[pb(index = 2)]
7880
pub data: Vec<u8>,
81+
82+
#[pb(index = 3, one_of)]
83+
pub field_type: Option<FieldType>,
7984
}
8085

8186
impl GridCellPB {
82-
pub fn new(field_id: &str, data: Vec<u8>) -> Self {
87+
pub fn new(field_id: &str, field_type: FieldType, data: Vec<u8>) -> Self {
8388
Self {
8489
field_id: field_id.to_owned(),
8590
data,
91+
field_type: Some(field_type),
8692
}
8793
}
8894

8995
pub fn empty(field_id: &str) -> Self {
9096
Self {
9197
field_id: field_id.to_owned(),
9298
data: vec![],
99+
field_type: None,
93100
}
94101
}
95102
}

frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ pub trait CellDisplayable<CD> {
2424
decoded_field_type: &FieldType,
2525
field_rev: &FieldRevision,
2626
) -> FlowyResult<CellBytes>;
27+
28+
fn display_string(
29+
&self,
30+
cell_data: CellData<CD>,
31+
decoded_field_type: &FieldType,
32+
field_rev: &FieldRevision,
33+
) -> FlowyResult<String>;
2734
}
2835

2936
// CD: Short for CellData. This type is the type return by apply_changeset function.
@@ -84,29 +91,75 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
8491
pub fn decode_any_cell_data<T: TryInto<AnyCellData, Error = FlowyError> + Debug>(
8592
data: T,
8693
field_rev: &FieldRevision,
87-
) -> CellBytes {
94+
) -> (FieldType, CellBytes) {
95+
let to_field_type = field_rev.ty.into();
8896
match data.try_into() {
8997
Ok(any_cell_data) => {
9098
let AnyCellData { data, field_type } = any_cell_data;
91-
let to_field_type = field_rev.ty.into();
9299
match try_decode_cell_data(data.into(), &field_type, &to_field_type, field_rev) {
93-
Ok(cell_bytes) => cell_bytes,
100+
Ok(cell_bytes) => (field_type, cell_bytes),
94101
Err(e) => {
95102
tracing::error!("Decode cell data failed, {:?}", e);
96-
CellBytes::default()
103+
(field_type, CellBytes::default())
97104
}
98105
}
99106
}
100107
Err(_err) => {
101108
// It's okay to ignore this error, because it's okay that the current cell can't
102109
// display the existing cell data. For example, the UI of the text cell will be blank if
103110
// the type of the data of cell is Number.
104-
CellBytes::default()
111+
112+
(to_field_type, CellBytes::default())
113+
}
114+
}
115+
}
116+
117+
pub fn decode_cell_data_to_string(
118+
cell_data: CellData<String>,
119+
from_field_type: &FieldType,
120+
to_field_type: &FieldType,
121+
field_rev: &FieldRevision,
122+
) -> FlowyResult<String> {
123+
let cell_data = cell_data.try_into_inner()?;
124+
let get_cell_display_str = || {
125+
let field_type: FieldTypeRevision = to_field_type.into();
126+
let result = match to_field_type {
127+
FieldType::RichText => field_rev
128+
.get_type_option::<RichTextTypeOptionPB>(field_type)?
129+
.display_string(cell_data.into(), from_field_type, field_rev),
130+
FieldType::Number => field_rev
131+
.get_type_option::<NumberTypeOptionPB>(field_type)?
132+
.display_string(cell_data.into(), from_field_type, field_rev),
133+
FieldType::DateTime => field_rev
134+
.get_type_option::<DateTypeOptionPB>(field_type)?
135+
.display_string(cell_data.into(), from_field_type, field_rev),
136+
FieldType::SingleSelect => field_rev
137+
.get_type_option::<SingleSelectTypeOptionPB>(field_type)?
138+
.display_string(cell_data.into(), from_field_type, field_rev),
139+
FieldType::MultiSelect => field_rev
140+
.get_type_option::<MultiSelectTypeOptionPB>(field_type)?
141+
.display_string(cell_data.into(), from_field_type, field_rev),
142+
FieldType::Checkbox => field_rev
143+
.get_type_option::<CheckboxTypeOptionPB>(field_type)?
144+
.display_string(cell_data.into(), from_field_type, field_rev),
145+
FieldType::URL => field_rev
146+
.get_type_option::<URLTypeOptionPB>(field_type)?
147+
.display_string(cell_data.into(), from_field_type, field_rev),
148+
};
149+
Some(result)
150+
};
151+
152+
match get_cell_display_str() {
153+
Some(Ok(s)) => Ok(s),
154+
Some(Err(err)) => {
155+
tracing::error!("{:?}", err);
156+
Ok("".to_owned())
105157
}
158+
None => Ok("".to_owned()),
106159
}
107160
}
108161

109-
/// Use the `to_field_type`'s TypeOption to parse the cell data into `from_field_type`'s data.
162+
/// Use the `to_field_type`'s TypeOption to parse the cell data into `from_field_type` type's data.
110163
///
111164
/// Each `FieldType` has its corresponding `TypeOption` that implements the `CellDisplayable`
112165
/// and `CellDataOperation` traits.

frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ impl CellDisplayable<CheckboxCellData> for CheckboxTypeOptionPB {
4848
let cell_data = cell_data.try_into_inner()?;
4949
Ok(CellBytes::new(cell_data))
5050
}
51+
52+
fn display_string(
53+
&self,
54+
cell_data: CellData<CheckboxCellData>,
55+
_decoded_field_type: &FieldType,
56+
_field_rev: &FieldRevision,
57+
) -> FlowyResult<String> {
58+
let cell_data = cell_data.try_into_inner()?;
59+
Ok(cell_data.to_string())
60+
}
5161
}
5262

5363
impl CellDataOperation<CheckboxCellData, String> for CheckboxTypeOptionPB {

frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,17 @@ impl CellDisplayable<DateTimestamp> for DateTypeOptionPB {
127127
let date_cell_data = self.today_desc_from_timestamp(timestamp);
128128
CellBytes::from(date_cell_data)
129129
}
130+
131+
fn display_string(
132+
&self,
133+
cell_data: CellData<DateTimestamp>,
134+
_decoded_field_type: &FieldType,
135+
_field_rev: &FieldRevision,
136+
) -> FlowyResult<String> {
137+
let timestamp = cell_data.try_into_inner()?;
138+
let date_cell_data = self.today_desc_from_timestamp(timestamp);
139+
Ok(date_cell_data.date)
140+
}
130141
}
131142

132143
impl CellDataOperation<DateTimestamp, DateCellChangesetPB> for DateTypeOptionPB {

frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::entities::FieldType;
22
use crate::impl_type_option;
3-
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation};
3+
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
44
use crate::services::field::type_options::number_type_option::format::*;
55
use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBuilder};
66
use bytes::Bytes;
@@ -102,22 +102,43 @@ pub(crate) fn strip_currency_symbol<T: ToString>(s: T) -> String {
102102
s
103103
}
104104

105+
impl CellDisplayable<String> for NumberTypeOptionPB {
106+
fn display_data(
107+
&self,
108+
cell_data: CellData<String>,
109+
_decoded_field_type: &FieldType,
110+
_field_rev: &FieldRevision,
111+
) -> FlowyResult<CellBytes> {
112+
let cell_data: String = cell_data.try_into_inner()?;
113+
match self.format_cell_data(&cell_data) {
114+
Ok(num) => Ok(CellBytes::new(num.to_string())),
115+
Err(_) => Ok(CellBytes::default()),
116+
}
117+
}
118+
119+
fn display_string(
120+
&self,
121+
cell_data: CellData<String>,
122+
_decoded_field_type: &FieldType,
123+
_field_rev: &FieldRevision,
124+
) -> FlowyResult<String> {
125+
let cell_data: String = cell_data.try_into_inner()?;
126+
Ok(cell_data)
127+
}
128+
}
129+
105130
impl CellDataOperation<String, String> for NumberTypeOptionPB {
106131
fn decode_cell_data(
107132
&self,
108133
cell_data: CellData<String>,
109134
decoded_field_type: &FieldType,
110-
_field_rev: &FieldRevision,
135+
field_rev: &FieldRevision,
111136
) -> FlowyResult<CellBytes> {
112137
if decoded_field_type.is_date() {
113138
return Ok(CellBytes::default());
114139
}
115140

116-
let cell_data: String = cell_data.try_into_inner()?;
117-
match self.format_cell_data(&cell_data) {
118-
Ok(num) => Ok(CellBytes::new(num.to_string())),
119-
Err(_) => Ok(CellBytes::default()),
120-
}
141+
self.display_data(cell_data, decoded_field_type, field_rev)
121142
}
122143

123144
fn apply_changeset(

frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,21 @@ where
120120
) -> FlowyResult<CellBytes> {
121121
CellBytes::from(self.selected_select_option(cell_data))
122122
}
123+
124+
fn display_string(
125+
&self,
126+
cell_data: CellData<SelectOptionIds>,
127+
_decoded_field_type: &FieldType,
128+
_field_rev: &FieldRevision,
129+
) -> FlowyResult<String> {
130+
Ok(self
131+
.selected_select_option(cell_data)
132+
.select_options
133+
.into_iter()
134+
.map(|option| option.name)
135+
.collect::<Vec<String>>()
136+
.join(SELECTION_IDS_SEPARATOR))
137+
}
123138
}
124139

125140
pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult<Box<dyn SelectOptionOperation>> {

frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ mod tests {
1717
type_option
1818
.decode_cell_data(1647251762.into(), &field_type, &field_rev)
1919
.unwrap()
20-
.parser::<DateCellDataParser>()
20+
.parser::<TextCellDataParser>()
2121
.unwrap()
22-
.date,
23-
"Mar 14,2022".to_owned()
22+
.as_ref(),
23+
"Mar 14,2022"
2424
);
2525
}
2626

@@ -40,10 +40,10 @@ mod tests {
4040
type_option
4141
.decode_cell_data(option_id.into(), &field_type, &field_rev)
4242
.unwrap()
43-
.parser::<SelectOptionCellDataParser>()
43+
.parser::<TextCellDataParser>()
4444
.unwrap()
45-
.select_options,
46-
vec![done_option],
45+
.to_string(),
46+
done_option.name,
4747
);
4848
}
4949
}

frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::entities::FieldType;
22
use crate::impl_type_option;
33
use crate::services::cell::{
4-
try_decode_cell_data, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation, CellDisplayable,
5-
FromCellString,
4+
decode_cell_data_to_string, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation,
5+
CellDisplayable, FromCellString,
66
};
77
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
88
use bytes::Bytes;
@@ -44,6 +44,16 @@ impl CellDisplayable<String> for RichTextTypeOptionPB {
4444
let cell_str: String = cell_data.try_into_inner()?;
4545
Ok(CellBytes::new(cell_str))
4646
}
47+
48+
fn display_string(
49+
&self,
50+
cell_data: CellData<String>,
51+
_decoded_field_type: &FieldType,
52+
_field_rev: &FieldRevision,
53+
) -> FlowyResult<String> {
54+
let cell_str: String = cell_data.try_into_inner()?;
55+
Ok(cell_str)
56+
}
4757
}
4858

4959
impl CellDataOperation<String, String> for RichTextTypeOptionPB {
@@ -57,8 +67,10 @@ impl CellDataOperation<String, String> for RichTextTypeOptionPB {
5767
|| decoded_field_type.is_single_select()
5868
|| decoded_field_type.is_multi_select()
5969
|| decoded_field_type.is_number()
70+
|| decoded_field_type.is_url()
6071
{
61-
try_decode_cell_data(cell_data, decoded_field_type, decoded_field_type, field_rev)
72+
let s = decode_cell_data_to_string(cell_data, decoded_field_type, decoded_field_type, field_rev);
73+
Ok(CellBytes::new(s.unwrap_or_else(|_| "".to_owned())))
6274
} else {
6375
self.display_data(cell_data, decoded_field_type, field_rev)
6476
}
@@ -85,6 +97,14 @@ impl AsRef<str> for TextCellData {
8597
}
8698
}
8799

100+
impl std::ops::Deref for TextCellData {
101+
type Target = String;
102+
103+
fn deref(&self) -> &Self::Target {
104+
&self.0
105+
}
106+
}
107+
88108
impl FromCellString for TextCellData {
89109
fn from_cell_str(s: &str) -> FlowyResult<Self>
90110
where
@@ -94,6 +114,12 @@ impl FromCellString for TextCellData {
94114
}
95115
}
96116

117+
impl ToString for TextCellData {
118+
fn to_string(&self) -> String {
119+
self.0.clone()
120+
}
121+
}
122+
97123
pub struct TextCellDataParser();
98124
impl CellBytesParser for TextCellDataParser {
99125
type Object = TextCellData;

0 commit comments

Comments
 (0)