import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'grid_service.dart'; part 'grid_bloc.freezed.dart'; class GridBloc extends Bloc { final GridService service; final View view; late Grid? _grid; late List? _fields; GridBloc({required this.view, required this.service}) : super(GridState.initial()) { on( (event, emit) async { await event.map( initial: (Initial value) async { await _loadGrid(emit); await _loadFields(emit); await _loadGridInfo(emit); }, createRow: (_CreateRow value) { service.createRow(gridId: view.id); }, delete: (_Delete value) {}, rename: (_Rename value) {}, updateDesc: (_Desc value) {}, ); }, ); } @override Future close() async { return super.close(); } Future _loadGrid(Emitter emit) async { final result = await service.openGrid(gridId: view.id); result.fold( (grid) { _grid = grid; }, (err) { emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)))); }, ); } Future _loadFields(Emitter emit) async { if (_grid != null) { final result = await service.getFields(gridId: _grid!.id, fieldOrders: _grid!.fieldOrders); result.fold( (fields) { _fields = fields.items; }, (err) { emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)))); }, ); } } Future _loadGridInfo(Emitter emit) async { if (_grid != null && _fields != null) { final result = await service.getRows(gridId: _grid!.id, rowOrders: _grid!.rowOrders); result.fold((repeatedRow) { final rows = repeatedRow.items; final gridInfo = GridInfo(rows: rows, fields: _fields!); emit( state.copyWith(loadingState: GridLoadingState.finish(left(unit)), gridInfo: some(left(gridInfo))), ); }, (err) { emit( state.copyWith(loadingState: GridLoadingState.finish(right(err)), gridInfo: none()), ); }); } } } @freezed abstract class GridEvent with _$GridEvent { const factory GridEvent.initial() = Initial; const factory GridEvent.rename(String gridId, String name) = _Rename; const factory GridEvent.updateDesc(String gridId, String desc) = _Desc; const factory GridEvent.delete(String gridId) = _Delete; const factory GridEvent.createRow() = _CreateRow; } @freezed abstract class GridState with _$GridState { const factory GridState({ required GridLoadingState loadingState, required Option> gridInfo, }) = _GridState; factory GridState.initial() => GridState( loadingState: const _Loading(), gridInfo: none(), ); } @freezed class GridLoadingState with _$GridLoadingState { const factory GridLoadingState.loading() = _Loading; const factory GridLoadingState.finish(Either successOrFail) = _Finish; } class GridInfo { List rows; List fields; GridInfo({ required this.rows, required this.fields, }); RowInfo rowInfoAtIndex(int index) { final row = rows[index]; return RowInfo( fields: fields, cellMap: row.cellByFieldId, ); } int numberOfRows() { return rows.length; } } class RowInfo { List fields; Map cellMap; RowInfo({ required this.fields, required this.cellMap, }); }