| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 | 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 'cell/cell_service.dart';import 'grid_service.dart';import 'row/row_service.dart';part 'grid_bloc.freezed.dart';class GridBloc extends Bloc<GridEvent, GridState> {  final GridService _gridService;  final GridFieldCache fieldCache;  late final GridRowCache rowCache;  late final GridCellCache cellCache;  GridBloc({required View view})      : _gridService = GridService(gridId: view.id),        fieldCache = GridFieldCache(gridId: view.id),        super(GridState.initial(view.id)) {    rowCache = GridRowCache(      gridId: view.id,      fieldDelegate: GridRowCacheDelegateImpl(fieldCache),    );    cellCache = GridCellCache(      gridId: view.id,      fieldDelegate: GridCellCacheDelegateImpl(fieldCache),    );    on<GridEvent>(      (event, emit) async {        await event.map(          initial: (InitialGrid value) async {            _startListening();            await _loadGrid(emit);          },          createRow: (_CreateRow value) {            _gridService.createRow();          },          didReceiveRowUpdate: (_DidReceiveRowUpdate value) {            emit(state.copyWith(rows: value.rows, listState: value.listState));          },          didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {            emit(state.copyWith(rows: rowCache.clonedRows, fields: value.fields));          },        );      },    );  }  @override  Future<void> close() async {    await _gridService.closeGrid();    await cellCache.dispose();    await rowCache.dispose();    await fieldCache.dispose();    return super.close();  }  void _startListening() {    fieldCache.addListener(      listenWhen: () => !isClosed,      onChanged: (fields) => add(GridEvent.didReceiveFieldUpdate(fields)),    );    rowCache.addListener(      listenWhen: () => !isClosed,      onChanged: (rows, listState) => add(GridEvent.didReceiveRowUpdate(rowCache.clonedRows, listState)),    );  }  Future<void> _loadGrid(Emitter<GridState> emit) async {    final result = await _gridService.loadGrid();    return Future(      () => result.fold(        (grid) async => await _loadFields(grid, emit),        (err) => emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)))),      ),    );  }  Future<void> _loadFields(Grid grid, Emitter<GridState> emit) async {    final result = await _gridService.getFields(fieldOrders: grid.fieldOrders);    return Future(      () => result.fold(        (fields) {          fieldCache.fields = fields.items;          rowCache.resetRows(grid.blockOrders);          emit(state.copyWith(            grid: Some(grid),            fields: fieldCache.clonedFields,            rows: rowCache.clonedRows,            loadingState: GridLoadingState.finish(left(unit)),          ));        },        (err) => emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)))),      ),    );  }}@freezedclass GridEvent with _$GridEvent {  const factory GridEvent.initial() = InitialGrid;  const factory GridEvent.createRow() = _CreateRow;  const factory GridEvent.didReceiveRowUpdate(List<GridRow> rows, GridRowChangeReason listState) = _DidReceiveRowUpdate;  const factory GridEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;}@freezedclass GridState with _$GridState {  const factory GridState({    required String gridId,    required Option<Grid> grid,    required List<Field> fields,    required List<GridRow> rows,    required GridLoadingState loadingState,    required GridRowChangeReason listState,  }) = _GridState;  factory GridState.initial(String gridId) => GridState(        fields: [],        rows: [],        grid: none(),        gridId: gridId,        loadingState: const _Loading(),        listState: const InitialListState(),      );}@freezedclass GridLoadingState with _$GridLoadingState {  const factory GridLoadingState.loading() = _Loading;  const factory GridLoadingState.finish(Either<Unit, FlowyError> successOrFail) = _Finish;}
 |