chore: cell select option editor

This commit is contained in:
appflowy 2022-04-03 22:22:54 +08:00
parent aa9e3d065b
commit 5c3500e24c
26 changed files with 364 additions and 102 deletions

View File

@ -0,0 +1,102 @@
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'cell_service.dart';
part 'selection_editor_bloc.freezed.dart';
class SelectionEditorBloc extends Bloc<SelectionEditorEvent, SelectionEditorState> {
final CellService service = CellService();
final FieldListener _listener;
SelectionEditorBloc({
required String gridId,
required Field field,
}) : _listener = FieldListener(fieldId: field.id),
super(SelectionEditorState.initial(gridId, field)) {
on<SelectionEditorEvent>(
(event, emit) async {
await event.map(
initial: (_Initial value) async {
_startListening();
_loadOptions();
},
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(field: value.field));
_loadOptions();
},
didReceiveOptions: (_DidReceiveOptions value) {
emit(state.copyWith(options: value.options));
},
);
},
);
}
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _startListening() {
_listener.updateFieldNotifier.addPublishListener((result) {
result.fold(
(field) => add(SelectionEditorEvent.didReceiveFieldUpdate(field)),
(err) => Log.error(err),
);
});
}
void _loadOptions() async {
final result = await FieldContextLoaderAdaptor(gridId: state.gridId, field: state.field).load();
result.fold(
(context) {
List<SelectOption> options = [];
switch (state.field.fieldType) {
case FieldType.MultiSelect:
options.addAll(MultiSelectTypeOption.fromBuffer(context.typeOptionData).options);
break;
case FieldType.SingleSelect:
options.addAll(SingleSelectTypeOption.fromBuffer(context.typeOptionData).options);
break;
default:
Log.error("Invalid field type, expect single select or multiple select");
break;
}
add(SelectionEditorEvent.didReceiveOptions(options));
},
(err) => Log.error(err),
);
}
}
@freezed
class SelectionEditorEvent with _$SelectionEditorEvent {
const factory SelectionEditorEvent.initial() = _Initial;
const factory SelectionEditorEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
const factory SelectionEditorEvent.didReceiveOptions(List<SelectOption> options) = _DidReceiveOptions;
}
@freezed
class SelectionEditorState with _$SelectionEditorState {
const factory SelectionEditorState({
required String gridId,
required Field field,
required List<SelectOption> options,
}) = _SelectionEditorState;
factory SelectionEditorState.initial(String gridId, Field field) {
return SelectionEditorState(
gridId: gridId,
field: field,
options: [],
);
}
}

View File

@ -0,0 +1,51 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'package:flowy_infra/notifier.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:app_flowy/core/notification_helper.dart';
typedef UpdateFieldNotifiedValue = Either<Field, FlowyError>;
class FieldListener {
final String fieldId;
PublishNotifier<UpdateFieldNotifiedValue> updateFieldNotifier = PublishNotifier();
StreamSubscription<SubscribeObject>? _subscription;
GridNotificationParser? _parser;
FieldListener({required this.fieldId});
void start() {
_parser = GridNotificationParser(
id: fieldId,
callback: (ty, result) {
_handleObservableType(ty, result);
},
);
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
}
void _handleObservableType(GridNotification ty, Either<Uint8List, FlowyError> result) {
switch (ty) {
case GridNotification.DidUpdateField:
result.fold(
(payload) => updateFieldNotifier.value = left(Field.fromBuffer(payload)),
(error) => updateFieldNotifier.value = right(error),
);
break;
default:
break;
}
}
Future<void> stop() async {
_parser = null;
await _subscription?.cancel();
updateFieldNotifier.dispose();
}
}

View File

@ -132,16 +132,20 @@ class NewFieldContextLoader extends FieldContextLoader {
}
class FieldContextLoaderAdaptor extends FieldContextLoader {
final GridFieldCellContext data;
final String gridId;
final Field field;
FieldContextLoaderAdaptor(this.data);
FieldContextLoaderAdaptor({
required this.gridId,
required this.field,
});
@override
Future<Either<EditFieldContext, FlowyError>> load() {
final payload = GetEditFieldContextPayload.create()
..gridId = data.gridId
..fieldId = data.field.id
..fieldType = data.field.fieldType;
..gridId = gridId
..fieldId = field.id
..fieldType = field.fieldType;
return GridEventGetEditFieldContext(payload).send();
}

View File

@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
import 'controller/grid_scroll.dart';
import 'layout/layout.dart';
import 'layout/sizes.dart';
import 'widgets/content/grid_row.dart';
import 'widgets/row/grid_row.dart';
import 'widgets/footer/grid_footer.dart';
import 'widgets/header/grid_header.dart';
import 'widgets/toolbar/grid_toolbar.dart';
@ -101,7 +101,7 @@ class _FlowyGridState extends State<FlowyGrid> {
controller: _scrollController.verticalController,
slivers: [
_renderToolbar(gridId),
_renderHeader(gridId),
GridHeader(gridId: gridId, fields: List.from(state.fields)),
_renderRows(context),
const GridFooter(),
],
@ -144,21 +144,6 @@ class _FlowyGridState extends State<FlowyGrid> {
);
}
Widget _renderHeader(String gridId) {
return BlocBuilder<GridBloc, GridState>(
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
builder: (context, state) {
return GridHeader(gridId: gridId, fields: List.from(state.fields));
// return SliverPersistentHeader(
// delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)),
// floating: true,
// pinned: true,
// );
},
);
}
Widget _renderRows(BuildContext context) {
return BlocBuilder<GridBloc, GridState>(
buildWhen: (previous, current) {

View File

@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart';
import 'checkbox_cell.dart';
import 'date_cell.dart';
import 'number_cell.dart';
import 'selection_cell.dart';
import 'selection_cell/selection_cell.dart';
import 'text_cell.dart';
Widget buildGridCell(String rowId, Field field, FutureCellData cellData) {

View File

@ -0,0 +1,7 @@
export 'cell_builder.dart';
export 'cell_container.dart';
export 'text_cell.dart';
export 'number_cell.dart';
export 'date_cell.dart';
export 'checkbox_cell.dart';
export 'selection_cell/selection_cell.dart';

View File

@ -0,0 +1,77 @@
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SelectionBadge extends StatelessWidget {
final SelectOption option;
const SelectionBadge({required this.option, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: option.color.make(context),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(6.0),
),
child: FlowyText.medium(option.name, fontSize: 12),
);
}
}
extension SelectOptionColorExtension on SelectOptionColor {
Color make(BuildContext context) {
final theme = context.watch<AppTheme>();
switch (this) {
case SelectOptionColor.Purple:
return theme.tint1;
case SelectOptionColor.Pink:
return theme.tint2;
case SelectOptionColor.LightPink:
return theme.tint3;
case SelectOptionColor.Orange:
return theme.tint4;
case SelectOptionColor.Yellow:
return theme.tint5;
case SelectOptionColor.Lime:
return theme.tint6;
case SelectOptionColor.Green:
return theme.tint7;
case SelectOptionColor.Aqua:
return theme.tint8;
case SelectOptionColor.Blue:
return theme.tint9;
default:
throw ArgumentError;
}
}
String optionName() {
switch (this) {
case SelectOptionColor.Purple:
return LocaleKeys.grid_selectOption_purpleColor.tr();
case SelectOptionColor.Pink:
return LocaleKeys.grid_selectOption_pinkColor.tr();
case SelectOptionColor.LightPink:
return LocaleKeys.grid_selectOption_lightPinkColor.tr();
case SelectOptionColor.Orange:
return LocaleKeys.grid_selectOption_orangeColor.tr();
case SelectOptionColor.Yellow:
return LocaleKeys.grid_selectOption_yellowColor.tr();
case SelectOptionColor.Lime:
return LocaleKeys.grid_selectOption_limeColor.tr();
case SelectOptionColor.Green:
return LocaleKeys.grid_selectOption_greenColor.tr();
case SelectOptionColor.Aqua:
return LocaleKeys.grid_selectOption_aquaColor.tr();
case SelectOptionColor.Blue:
return LocaleKeys.grid_selectOption_blueColor.tr();
default:
throw ArgumentError;
}
}
}

View File

@ -0,0 +1,45 @@
import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart';
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'selection.dart';
class SelectionEditor extends StatelessWidget {
final GridCellData cellData;
const SelectionEditor({required this.cellData, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SelectionEditorBloc(gridId: cellData.gridId, field: cellData.field),
child: BlocBuilder<SelectionEditorBloc, SelectionEditorState>(
builder: (context, state) {
return Container();
},
),
);
}
}
class _SelectionCell extends StatelessWidget {
final SelectOption option;
const _SelectionCell({required this.option, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return InkWell(
onTap: () {},
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.hover),
builder: (_, onHover) {
return SelectionBadge(option: option);
},
),
);
}
}

View File

@ -49,7 +49,10 @@ class GridFieldCell extends StatelessWidget {
void _showFieldEditor(BuildContext context) {
FieldEditor(
gridId: fieldCellContext.gridId,
fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext),
fieldContextLoader: FieldContextLoaderAdaptor(
gridId: fieldCellContext.gridId,
field: fieldCellContext.field,
),
).show(context);
}
}

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/workspace/application/grid/field/type_option/edit_option_bloc.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
@ -183,56 +184,3 @@ class _SelectOptionColorCell extends StatelessWidget {
);
}
}
extension SelectOptionColorExtension on SelectOptionColor {
Color color(BuildContext context) {
final theme = context.watch<AppTheme>();
switch (this) {
case SelectOptionColor.Purple:
return theme.tint1;
case SelectOptionColor.Pink:
return theme.tint2;
case SelectOptionColor.LightPink:
return theme.tint3;
case SelectOptionColor.Orange:
return theme.tint4;
case SelectOptionColor.Yellow:
return theme.tint5;
case SelectOptionColor.Lime:
return theme.tint6;
case SelectOptionColor.Green:
return theme.tint7;
case SelectOptionColor.Aqua:
return theme.tint8;
case SelectOptionColor.Blue:
return theme.tint9;
default:
throw ArgumentError;
}
}
String optionName() {
switch (this) {
case SelectOptionColor.Purple:
return LocaleKeys.grid_selectOption_purpleColor.tr();
case SelectOptionColor.Pink:
return LocaleKeys.grid_selectOption_pinkColor.tr();
case SelectOptionColor.LightPink:
return LocaleKeys.grid_selectOption_lightPinkColor.tr();
case SelectOptionColor.Orange:
return LocaleKeys.grid_selectOption_orangeColor.tr();
case SelectOptionColor.Yellow:
return LocaleKeys.grid_selectOption_yellowColor.tr();
case SelectOptionColor.Lime:
return LocaleKeys.grid_selectOption_limeColor.tr();
case SelectOptionColor.Green:
return LocaleKeys.grid_selectOption_greenColor.tr();
case SelectOptionColor.Aqua:
return LocaleKeys.grid_selectOption_aquaColor.tr();
case SelectOptionColor.Blue:
return LocaleKeys.grid_selectOption_blueColor.tr();
default:
throw ArgumentError;
}
}
}

View File

@ -1,14 +1,13 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'cell_builder.dart';
import 'cell_container.dart';
class GridRowWidget extends StatefulWidget {
final GridRowData data;

View File

@ -97,14 +97,9 @@ class _GridPropertyCell extends StatelessWidget {
hoverColor: theme.hover,
leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
onTap: () {
final fieldCellContext = GridFieldCellContext(
gridId: gridId,
field: field,
);
FieldEditor(
gridId: gridId,
fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext),
fieldContextLoader: FieldContextLoaderAdaptor(gridId: gridId, field: field),
).show(context, anchorDirection: AnchorDirection.bottomRight);
},
),

View File

@ -11,17 +11,19 @@ import 'package:protobuf/protobuf.dart' as $pb;
class GridNotification extends $pb.ProtobufEnum {
static const GridNotification Unknown = GridNotification._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
static const GridNotification GridDidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidCreateBlock');
static const GridNotification DidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidCreateBlock');
static const GridNotification DidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow');
static const GridNotification GridDidUpdateCells = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells');
static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields');
static const GridNotification DidUpdateField = GridNotification._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateField');
static const $core.List<GridNotification> values = <GridNotification> [
Unknown,
GridDidCreateBlock,
DidCreateBlock,
DidUpdateRow,
GridDidUpdateCells,
DidUpdateFields,
DidUpdateField,
];
static final $core.Map<$core.int, GridNotification> _byValue = $pb.ProtobufEnum.initByValue(values);

View File

@ -13,12 +13,13 @@ const GridNotification$json = const {
'1': 'GridNotification',
'2': const [
const {'1': 'Unknown', '2': 0},
const {'1': 'GridDidCreateBlock', '2': 11},
const {'1': 'DidCreateBlock', '2': 11},
const {'1': 'DidUpdateRow', '2': 20},
const {'1': 'GridDidUpdateCells', '2': 30},
const {'1': 'DidUpdateFields', '2': 40},
const {'1': 'DidUpdateField', '2': 41},
],
};
/// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIQCgxEaWRVcGRhdGVSb3cQFBIWChJHcmlkRGlkVXBkYXRlQ2VsbHMQHhITCg9EaWRVcGRhdGVGaWVsZHMQKA==');
final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhAKDERpZFVwZGF0ZVJvdxAUEhYKEkdyaWREaWRVcGRhdGVDZWxscxAeEhMKD0RpZFVwZGF0ZUZpZWxkcxAoEhIKDkRpZFVwZGF0ZUZpZWxkECk=');

View File

@ -5,13 +5,11 @@ const OBSERVABLE_CATEGORY: &str = "Grid";
#[derive(ProtoBuf_Enum, Debug)]
pub enum GridNotification {
Unknown = 0,
GridDidCreateBlock = 11,
DidCreateBlock = 11,
DidUpdateRow = 20,
GridDidUpdateCells = 30,
DidUpdateFields = 40,
DidUpdateField = 41,
}
impl std::default::Default for GridNotification {

View File

@ -26,10 +26,11 @@
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum GridNotification {
Unknown = 0,
GridDidCreateBlock = 11,
DidCreateBlock = 11,
DidUpdateRow = 20,
GridDidUpdateCells = 30,
DidUpdateFields = 40,
DidUpdateField = 41,
}
impl ::protobuf::ProtobufEnum for GridNotification {
@ -40,10 +41,11 @@ impl ::protobuf::ProtobufEnum for GridNotification {
fn from_i32(value: i32) -> ::std::option::Option<GridNotification> {
match value {
0 => ::std::option::Option::Some(GridNotification::Unknown),
11 => ::std::option::Option::Some(GridNotification::GridDidCreateBlock),
11 => ::std::option::Option::Some(GridNotification::DidCreateBlock),
20 => ::std::option::Option::Some(GridNotification::DidUpdateRow),
30 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells),
40 => ::std::option::Option::Some(GridNotification::DidUpdateFields),
41 => ::std::option::Option::Some(GridNotification::DidUpdateField),
_ => ::std::option::Option::None
}
}
@ -51,10 +53,11 @@ impl ::protobuf::ProtobufEnum for GridNotification {
fn values() -> &'static [Self] {
static values: &'static [GridNotification] = &[
GridNotification::Unknown,
GridNotification::GridDidCreateBlock,
GridNotification::DidCreateBlock,
GridNotification::DidUpdateRow,
GridNotification::GridDidUpdateCells,
GridNotification::DidUpdateFields,
GridNotification::DidUpdateField,
];
values
}
@ -83,10 +86,10 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x17dart_notification.proto*v\n\x10GridNotification\x12\x0b\n\x07Unkno\
wn\x10\0\x12\x16\n\x12GridDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUpdateR\
ow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDidUpdat\
eFields\x10(b\x06proto3\
\n\x17dart_notification.proto*\x86\x01\n\x10GridNotification\x12\x0b\n\
\x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUp\
dateRow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDid\
UpdateFields\x10(\x12\x12\n\x0eDidUpdateField\x10)b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -2,8 +2,9 @@ syntax = "proto3";
enum GridNotification {
Unknown = 0;
GridDidCreateBlock = 11;
DidCreateBlock = 11;
DidUpdateRow = 20;
GridDidUpdateCells = 30;
DidUpdateFields = 40;
DidUpdateField = 41;
}

View File

@ -97,6 +97,7 @@ impl ClientGridEditor {
}
pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> {
let field_id = params.field_id.clone();
let deserializer = match self.pad.read().await.get_field(&params.field_id) {
None => return Err(ErrorCode::FieldDoesNotExist.into()),
Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()),
@ -104,6 +105,7 @@ impl ClientGridEditor {
let _ = self.modify(|grid| Ok(grid.update_field(params, deserializer)?)).await?;
let _ = self.notify_did_update_fields().await?;
let _ = self.notify_did_update_field(&field_id).await?;
Ok(())
}
@ -133,6 +135,7 @@ impl ClientGridEditor {
.modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?))
.await?;
let _ = self.notify_did_update_fields().await?;
let _ = self.notify_did_update_field(field_id).await?;
Ok(())
}
@ -294,7 +297,19 @@ impl ClientGridEditor {
}
pub async fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> FlowyResult<Vec<FieldMeta>> {
let mut field_metas = self.pad.read().await.get_field_metas(field_orders)?;
let expected_len = match field_orders.as_ref() {
None => 0,
Some(field_orders) => field_orders.len(),
};
let field_metas = self.pad.read().await.get_field_metas(field_orders)?;
debug_assert!(field_metas.len() == expected_len);
if field_metas.len() != expected_len {
tracing::error!(
"This is a bug. The len of the field_metas should equal to {}",
expected_len
);
}
// field_metas.retain(|field_meta| field_meta.visibility);
Ok(field_metas)
}
@ -368,6 +383,20 @@ impl ClientGridEditor {
.send();
Ok(())
}
async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> {
let field_orders: RepeatedFieldOrder = vec![FieldOrder::from(field_id)].into();
let mut field_metas = self.get_field_metas(Some(field_orders)).await?;
debug_assert!(field_metas.len() == 1);
if let Some(field_meta) = field_metas.pop() {
send_dart_notification(&self.grid_id, GridNotification::DidUpdateField)
.payload(field_meta)
.send();
}
Ok(())
}
}
#[cfg(feature = "flowy_unit_test")]

View File

@ -100,6 +100,12 @@ impl std::convert::From<&FieldMeta> for FieldOrder {
}
}
impl std::convert::From<&str> for FieldOrder {
fn from(s: &str) -> Self {
FieldOrder { field_id: s.to_owned() }
}
}
#[derive(Debug, Default, ProtoBuf)]
pub struct GetEditFieldContextPayload {
#[pb(index = 1)]
@ -193,6 +199,12 @@ impl std::ops::Deref for RepeatedFieldOrder {
}
}
impl std::convert::From<Vec<FieldOrder>> for RepeatedFieldOrder {
fn from(field_orders: Vec<FieldOrder>) -> Self {
RepeatedFieldOrder { items: field_orders }
}
}
#[derive(Debug, Default, Clone, ProtoBuf)]
pub struct RowOrder {
#[pb(index = 1)]