123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- import 'package:dartz/dartz.dart';
- import 'package:flowy_infra/notifier.dart';
- import 'package:flowy_sdk/dispatch/dispatch.dart';
- import 'package:flowy_sdk/log.dart';
- import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
- import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
- import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
- import 'package:flutter/foundation.dart';
- import 'package:freezed_annotation/freezed_annotation.dart';
- import 'package:protobuf/protobuf.dart';
- part 'field_service.freezed.dart';
- /// FieldService consists of lots of event functions. We define the events in the backend(Rust),
- /// you can find the corresponding event implementation in event_map.rs of the corresponding crate.
- ///
- /// You could check out the rust-lib/flowy-grid/event_map.rs for more information.
- class FieldService {
- final String gridId;
- final String fieldId;
- FieldService({required this.gridId, required this.fieldId});
- Future<Either<Unit, FlowyError>> moveField(int fromIndex, int toIndex) {
- final payload = MoveItemPayloadPB.create()
- ..gridId = gridId
- ..itemId = fieldId
- ..ty = MoveItemTypePB.MoveField
- ..fromIndex = fromIndex
- ..toIndex = toIndex;
- return GridEventMoveItem(payload).send();
- }
- Future<Either<Unit, FlowyError>> updateField({
- String? name,
- FieldType? fieldType,
- bool? frozen,
- bool? visibility,
- double? width,
- List<int>? typeOptionData,
- }) {
- var payload = FieldChangesetPayloadPB.create()
- ..gridId = gridId
- ..fieldId = fieldId;
- if (name != null) {
- payload.name = name;
- }
- if (fieldType != null) {
- payload.fieldType = fieldType;
- }
- if (frozen != null) {
- payload.frozen = frozen;
- }
- if (visibility != null) {
- payload.visibility = visibility;
- }
- if (width != null) {
- payload.width = width.toInt();
- }
- if (typeOptionData != null) {
- payload.typeOptionData = typeOptionData;
- }
- return GridEventUpdateField(payload).send();
- }
- // Create the field if it does not exist. Otherwise, update the field.
- static Future<Either<Unit, FlowyError>> insertField({
- required String gridId,
- required GridFieldPB field,
- List<int>? typeOptionData,
- String? startFieldId,
- }) {
- var payload = InsertFieldPayloadPB.create()
- ..gridId = gridId
- ..field_2 = field
- ..typeOptionData = typeOptionData ?? [];
- if (startFieldId != null) {
- payload.startFieldId = startFieldId;
- }
- return GridEventInsertField(payload).send();
- }
- static Future<Either<Unit, FlowyError>> updateFieldTypeOption({
- required String gridId,
- required String fieldId,
- required List<int> typeOptionData,
- }) {
- var payload = UpdateFieldTypeOptionPayloadPB.create()
- ..gridId = gridId
- ..fieldId = fieldId
- ..typeOptionData = typeOptionData;
- return GridEventUpdateFieldTypeOption(payload).send();
- }
- Future<Either<Unit, FlowyError>> deleteField() {
- final payload = DeleteFieldPayloadPB.create()
- ..gridId = gridId
- ..fieldId = fieldId;
- return GridEventDeleteField(payload).send();
- }
- Future<Either<Unit, FlowyError>> duplicateField() {
- final payload = DuplicateFieldPayloadPB.create()
- ..gridId = gridId
- ..fieldId = fieldId;
- return GridEventDuplicateField(payload).send();
- }
- Future<Either<FieldTypeOptionDataPB, FlowyError>> getFieldTypeOptionData({
- required FieldType fieldType,
- }) {
- final payload = GridFieldTypeOptionIdPB.create()
- ..gridId = gridId
- ..fieldId = fieldId
- ..fieldType = fieldType;
- return GridEventGetFieldTypeOption(payload).send().then((result) {
- return result.fold(
- (data) => left(data),
- (err) => right(err),
- );
- });
- }
- }
- @freezed
- class GridFieldCellContext with _$GridFieldCellContext {
- const factory GridFieldCellContext({
- required String gridId,
- required GridFieldPB field,
- }) = _GridFieldCellContext;
- }
- abstract class IFieldTypeOptionLoader {
- String get gridId;
- Future<Either<FieldTypeOptionDataPB, FlowyError>> load();
- Future<Either<FieldTypeOptionDataPB, FlowyError>> switchToField(String fieldId, FieldType fieldType) {
- final payload = EditFieldPayloadPB.create()
- ..gridId = gridId
- ..fieldId = fieldId
- ..fieldType = fieldType;
- return GridEventSwitchToField(payload).send();
- }
- }
- class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader {
- @override
- final String gridId;
- NewFieldTypeOptionLoader({
- required this.gridId,
- });
- @override
- Future<Either<FieldTypeOptionDataPB, FlowyError>> load() {
- final payload = CreateFieldPayloadPB.create()
- ..gridId = gridId
- ..fieldType = FieldType.RichText;
- return GridEventCreateFieldTypeOption(payload).send();
- }
- }
- class FieldTypeOptionLoader extends IFieldTypeOptionLoader {
- @override
- final String gridId;
- final GridFieldPB field;
- FieldTypeOptionLoader({
- required this.gridId,
- required this.field,
- });
- @override
- Future<Either<FieldTypeOptionDataPB, FlowyError>> load() {
- final payload = GridFieldTypeOptionIdPB.create()
- ..gridId = gridId
- ..fieldId = field.id
- ..fieldType = field.fieldType;
- return GridEventGetFieldTypeOption(payload).send();
- }
- }
- class TypeOptionDataController {
- final String gridId;
- final IFieldTypeOptionLoader _loader;
- late FieldTypeOptionDataPB _data;
- final PublishNotifier<GridFieldPB> _fieldNotifier = PublishNotifier();
- TypeOptionDataController({
- required this.gridId,
- required IFieldTypeOptionLoader loader,
- }) : _loader = loader;
- Future<Either<Unit, FlowyError>> loadData() async {
- final result = await _loader.load();
- return result.fold(
- (data) {
- data.freeze();
- _data = data;
- _fieldNotifier.value = data.field_2;
- return left(unit);
- },
- (err) {
- Log.error(err);
- return right(err);
- },
- );
- }
- GridFieldPB get field => _data.field_2;
- set field(GridFieldPB field) {
- _updateData(newField: field);
- }
- List<int> get typeOptionData => _data.typeOptionData;
- set fieldName(String name) {
- _updateData(newName: name);
- }
- set typeOptionData(List<int> typeOptionData) {
- _updateData(newTypeOptionData: typeOptionData);
- }
- void _updateData({String? newName, GridFieldPB? newField, List<int>? newTypeOptionData}) {
- _data = _data.rebuild((rebuildData) {
- if (newName != null) {
- rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) {
- rebuildField.name = newName;
- });
- }
- if (newField != null) {
- rebuildData.field_2 = newField;
- }
- if (newTypeOptionData != null) {
- rebuildData.typeOptionData = newTypeOptionData;
- }
- });
- _fieldNotifier.value = _data.field_2;
- FieldService.insertField(
- gridId: gridId,
- field: field,
- typeOptionData: typeOptionData,
- );
- }
- Future<void> switchToField(FieldType newFieldType) {
- return _loader.switchToField(field.id, newFieldType).then((result) {
- return result.fold(
- (fieldTypeOptionData) {
- _updateData(
- newField: fieldTypeOptionData.field_2,
- newTypeOptionData: fieldTypeOptionData.typeOptionData,
- );
- },
- (err) {
- Log.error(err);
- },
- );
- });
- }
- void Function() addFieldListener(void Function(GridFieldPB) callback) {
- listener() {
- callback(field);
- }
- _fieldNotifier.addListener(listener);
- return listener;
- }
- void removeFieldListener(void Function() listener) {
- _fieldNotifier.removeListener(listener);
- }
- }
|