فهرست منبع

chore: config checkbox ui

appflowy 3 سال پیش
والد
کامیت
e15d335fed

+ 14 - 0
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart

@@ -1,7 +1,9 @@
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
 
 class CellService {
   CellService();
@@ -19,4 +21,16 @@ class CellService {
       ..data = data;
     return GridEventUpdateCell(payload).send();
   }
+
+  Future<Either<Cell, FlowyError>> getCell({
+    required String gridId,
+    required String fieldId,
+    required String rowId,
+  }) {
+    final payload = CellIdentifierPayload.create()
+      ..gridId = gridId
+      ..fieldId = fieldId
+      ..rowId = rowId;
+    return GridEventGetCell(payload).send();
+  }
 }

+ 56 - 9
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart

@@ -1,5 +1,7 @@
+import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart';
 import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
@@ -8,17 +10,32 @@ import 'cell_service.dart';
 part 'checkbox_cell_bloc.freezed.dart';
 
 class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
-  final CellService service;
-  // final CellData cellData;
+  final CellService _service;
+  final CellListener _listener;
 
   CheckboxCellBloc({
-    required this.service,
+    required CellService service,
     required CellData cellData,
-  }) : super(CheckboxCellState.initial()) {
+  })  : _service = service,
+        _listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
+        super(CheckboxCellState.initial(cellData)) {
     on<CheckboxCellEvent>(
       (event, emit) async {
         await event.map(
-          initial: (_InitialCell value) async {},
+          initial: (_Initial value) {
+            _startListening();
+          },
+          select: (_Selected value) async {
+            service.updateCell(
+              gridId: state.cellData.gridId,
+              fieldId: state.cellData.field.id,
+              rowId: state.cellData.rowId,
+              data: !state.isSelected ? "Yes" : "No",
+            );
+          },
+          didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
+            emit(state.copyWith(isSelected: isSelected(value.cell)));
+          },
         );
       },
     );
@@ -28,18 +45,48 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
   Future<void> close() async {
     return super.close();
   }
+
+  void _startListening() {
+    _listener.updateCellNotifier.addPublishListener((result) {
+      result.fold(
+        (notificationData) async {
+          final result = await _service.getCell(
+            gridId: state.cellData.gridId,
+            fieldId: state.cellData.field.id,
+            rowId: state.cellData.rowId,
+          );
+          result.fold(
+            (cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)),
+            (err) => Log.error(err),
+          );
+        },
+        (err) => Log.error(err),
+      );
+    });
+    _listener.start();
+  }
 }
 
 @freezed
 class CheckboxCellEvent with _$CheckboxCellEvent {
-  const factory CheckboxCellEvent.initial() = _InitialCell;
+  const factory CheckboxCellEvent.initial() = _Initial;
+  const factory CheckboxCellEvent.select() = _Selected;
+  const factory CheckboxCellEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
 }
 
 @freezed
 class CheckboxCellState with _$CheckboxCellState {
   const factory CheckboxCellState({
-    required Cell? cell,
+    required CellData cellData,
+    required bool isSelected,
   }) = _CheckboxCellState;
 
-  factory CheckboxCellState.initial() => const CheckboxCellState(cell: null);
+  factory CheckboxCellState.initial(CellData cellData) {
+    return CheckboxCellState(cellData: cellData, isSelected: isSelected(cellData.cell));
+  }
+}
+
+bool isSelected(Cell? cell) {
+  final content = cell?.content ?? "";
+  return content == "Yes";
 }

+ 13 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart

@@ -1,5 +1,7 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';
+import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
@@ -20,7 +22,7 @@ class _CheckboxCellState extends State<CheckboxCell> {
 
   @override
   void initState() {
-    _cellBloc = getIt<CheckboxCellBloc>(param1: widget.cellData);
+    _cellBloc = getIt<CheckboxCellBloc>(param1: widget.cellData)..add(const CheckboxCellEvent.initial());
     super.initState();
   }
 
@@ -30,7 +32,16 @@ class _CheckboxCellState extends State<CheckboxCell> {
       value: _cellBloc,
       child: BlocBuilder<CheckboxCellBloc, CheckboxCellState>(
         builder: (context, state) {
-          return Container();
+          final icon = state.isSelected ? svgWidget('editor/editor_check') : svgWidget('editor/editor_uncheck');
+          return Align(
+            alignment: Alignment.centerLeft,
+            child: FlowyIconButton(
+              onPressed: () => context.read<CheckboxCellBloc>().add(const CheckboxCellEvent.select()),
+              iconPadding: EdgeInsets.zero,
+              icon: icon,
+              width: 23,
+            ),
+          );
         },
       ),
     );

+ 17 - 0
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart

@@ -239,6 +239,23 @@ class GridEventGetRow {
     }
 }
 
+class GridEventGetCell {
+     CellIdentifierPayload request;
+     GridEventGetCell(this.request);
+
+    Future<Either<Cell, FlowyError>> send() {
+    final request = FFIRequest.create()
+          ..event = GridEvent.GetCell.toString()
+          ..payload = requestToBytes(this.request);
+
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+           (okBytes) => left(Cell.fromBuffer(okBytes)),
+           (errBytes) => right(FlowyError.fromBuffer(errBytes)),
+        ));
+    }
+}
+
 class GridEventUpdateCell {
      CellMetaChangeset request;
      GridEventUpdateCell(this.request);

+ 4 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart

@@ -24,8 +24,9 @@ class GridEvent extends $pb.ProtobufEnum {
   static const GridEvent ApplySelectOptionChangeset = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset');
   static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
   static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
-  static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
-  static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset');
+  static const GridEvent GetCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCell');
+  static const GridEvent UpdateCell = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
+  static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(72, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset');
 
   static const $core.List<GridEvent> values = <GridEvent> [
     GetGridData,
@@ -42,6 +43,7 @@ class GridEvent extends $pb.ProtobufEnum {
     ApplySelectOptionChangeset,
     CreateRow,
     GetRow,
+    GetCell,
     UpdateCell,
     ApplySelectOptionCellChangeset,
   ];

+ 4 - 3
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart

@@ -26,10 +26,11 @@ const GridEvent$json = const {
     const {'1': 'ApplySelectOptionChangeset', '2': 32},
     const {'1': 'CreateRow', '2': 50},
     const {'1': 'GetRow', '2': 51},
-    const {'1': 'UpdateCell', '2': 70},
-    const {'1': 'ApplySelectOptionCellChangeset', '2': 71},
+    const {'1': 'GetCell', '2': 70},
+    const {'1': 'UpdateCell', '2': 71},
+    const {'1': 'ApplySelectOptionCellChangeset', '2': 72},
   ],
 };
 
 /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg4KClVwZGF0ZUNlbGwQRhIiCh5BcHBseVNlbGVjdE9wdGlvbkNlbGxDaGFuZ2VzZXQQRw==');
+final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSIgoeQXBwbHlTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0EEg=');

+ 13 - 0
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -190,6 +190,19 @@ pub(crate) async fn create_row_handler(
     Ok(())
 }
 
+#[tracing::instrument(level = "debug", skip_all, err)]
+pub(crate) async fn get_cell_handler(
+    data: Data<CellIdentifierPayload>,
+    manager: AppData<Arc<GridManager>>,
+) -> DataResult<Cell, FlowyError> {
+    let params: CellIdentifier = data.into_inner().try_into()?;
+    let editor = manager.get_grid_editor(&params.grid_id)?;
+    match editor.get_cell(&params).await {
+        None => data_result(Cell::new(&params.field_id, "".to_owned())),
+        Some(cell) => data_result(cell),
+    }
+}
+
 #[tracing::instrument(level = "debug", skip_all, err)]
 pub(crate) async fn update_cell_handler(
     data: Data<CellMetaChangeset>,

+ 6 - 2
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -21,6 +21,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
         .event(GridEvent::CreateRow, create_row_handler)
         .event(GridEvent::GetRow, get_row_handler)
         // Cell
+        .event(GridEvent::GetCell, get_cell_handler)
         .event(GridEvent::UpdateCell, update_cell_handler)
         // SelectOption
         .event(GridEvent::NewSelectOption, new_select_option_handler)
@@ -80,9 +81,12 @@ pub enum GridEvent {
     #[event(input = "RowIdentifierPayload", output = "Row")]
     GetRow = 51,
 
+    #[event(input = "CellIdentifierPayload", output = "Cell")]
+    GetCell = 70,
+
     #[event(input = "CellMetaChangeset")]
-    UpdateCell = 70,
+    UpdateCell = 71,
 
     #[event(input = "SelectOptionCellChangesetPayload")]
-    ApplySelectOptionCellChangeset = 71,
+    ApplySelectOptionCellChangeset = 72,
 }

+ 10 - 7
frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs

@@ -39,8 +39,9 @@ pub enum GridEvent {
     ApplySelectOptionChangeset = 32,
     CreateRow = 50,
     GetRow = 51,
-    UpdateCell = 70,
-    ApplySelectOptionCellChangeset = 71,
+    GetCell = 70,
+    UpdateCell = 71,
+    ApplySelectOptionCellChangeset = 72,
 }
 
 impl ::protobuf::ProtobufEnum for GridEvent {
@@ -64,8 +65,9 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             32 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset),
             50 => ::std::option::Option::Some(GridEvent::CreateRow),
             51 => ::std::option::Option::Some(GridEvent::GetRow),
-            70 => ::std::option::Option::Some(GridEvent::UpdateCell),
-            71 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset),
+            70 => ::std::option::Option::Some(GridEvent::GetCell),
+            71 => ::std::option::Option::Some(GridEvent::UpdateCell),
+            72 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset),
             _ => ::std::option::Option::None
         }
     }
@@ -86,6 +88,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             GridEvent::ApplySelectOptionChangeset,
             GridEvent::CreateRow,
             GridEvent::GetRow,
+            GridEvent::GetCell,
             GridEvent::UpdateCell,
             GridEvent::ApplySelectOptionCellChangeset,
         ];
@@ -116,15 +119,15 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0fevent_map.proto*\xd1\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
+    \n\x0fevent_map.proto*\xde\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
     \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\
     \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\
     leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\
     ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x13\n\x0fNewSe\
     lectOption\x10\x1e\x12\x1a\n\x16GetSelectOptionContext\x10\x1f\x12\x1e\n\
     \x1aApplySelectOptionChangeset\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\
-    \x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\"\n\x1eApplySelectOptionC\
-    ellChangeset\x10Gb\x06proto3\
+    \x06GetRow\x103\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\
+    \"\n\x1eApplySelectOptionCellChangeset\x10Hb\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 3 - 2
frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto

@@ -15,6 +15,7 @@ enum GridEvent {
     ApplySelectOptionChangeset = 32;
     CreateRow = 50;
     GetRow = 51;
-    UpdateCell = 70;
-    ApplySelectOptionCellChangeset = 71;
+    GetCell = 70;
+    UpdateCell = 71;
+    ApplySelectOptionCellChangeset = 72;
 }

+ 7 - 0
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -1,6 +1,7 @@
 use crate::dart_notification::{send_dart_notification, GridNotification};
 use crate::manager::GridUser;
 use crate::services::block_meta_manager::GridBlockMetaEditorManager;
+use crate::services::cell::CellIdentifier;
 use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
 use crate::services::persistence::block_index::BlockIndexPersistence;
 use crate::services::row::*;
@@ -264,6 +265,12 @@ impl ClientGridEditor {
         }
     }
 
+    pub async fn get_cell(&self, params: &CellIdentifier) -> Option<Cell> {
+        let field_meta = self.get_field_meta(&params.field_id).await?;
+        let row_meta = self.block_meta_manager.get_row_meta(&params.row_id).await.ok()??;
+        make_cell(&params.field_id, &field_meta, &row_meta)
+    }
+
     pub async fn get_cell_meta(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellMeta>> {
         let row_meta = self.block_meta_manager.get_row_meta(row_id).await?;
         match row_meta {

+ 7 - 1
frontend/rust-lib/flowy-grid/src/util.rs

@@ -1,5 +1,5 @@
 use crate::services::field::*;
-use flowy_grid_data_model::entities::BuildGridContext;
+use flowy_grid_data_model::entities::{BuildGridContext, FieldType};
 use flowy_sync::client_grid::GridBuilder;
 
 pub fn make_default_grid() -> BuildGridContext {
@@ -25,10 +25,16 @@ pub fn make_default_grid() -> BuildGridContext {
         .visibility(true)
         .build();
 
+    let checkbox_field = FieldBuilder::from_field_type(&FieldType::Checkbox)
+        .name("isReady")
+        .visibility(true)
+        .build();
+
     GridBuilder::default()
         .add_field(text_field)
         .add_field(single_select_field)
         .add_field(multi_select_field)
+        .add_field(checkbox_field)
         .add_empty_row()
         .add_empty_row()
         .add_empty_row()