chore: add board data controller

This commit is contained in:
appflowy 2022-08-11 15:00:36 +08:00
parent 8b535720ef
commit cefd571dd0
19 changed files with 141 additions and 151 deletions

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/builder.dart';
import 'package:appflowy_board/appflowy_board.dart';
@ -14,14 +13,16 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:collection';
import 'board_data_controller.dart';
part 'board_bloc.freezed.dart';
class BoardBloc extends Bloc<BoardEvent, BoardState> {
final GridDataController _gridDataController;
final BoardDataController _dataController;
late final AFBoardDataController boardDataController;
BoardBloc({required ViewPB view})
: _gridDataController = GridDataController(view: view),
: _dataController = BoardDataController(view: view),
super(BoardState.initial(view.id)) {
boardDataController = AFBoardDataController(
onMoveColumn: (
@ -51,7 +52,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
await _loadGrid(emit);
},
createRow: () {
_gridDataController.createRow();
_dataController.createRow();
},
didReceiveGridUpdate: (GridPB grid) {
emit(state.copyWith(grid: Some(grid)));
@ -66,39 +67,34 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
@override
Future<void> close() async {
await _gridDataController.dispose();
await _dataController.dispose();
return super.close();
}
GridRowCache? getRowCache(String blockId, String rowId) {
final GridBlockCache? blockCache = _gridDataController.blocks[blockId];
final GridBlockCache? blockCache = _dataController.blocks[blockId];
return blockCache?.rowCache;
}
void _startListening() {
_gridDataController.addListener(
_dataController.addListener(
onGridChanged: (grid) {
if (!isClosed) {
add(BoardEvent.didReceiveGridUpdate(grid));
}
},
onRowsChanged: (rowInfos, reason) {
if (!isClosed) {
_buildColumnItems(rowInfos);
}
},
onFieldsChanged: (fields) {
if (!isClosed) {
_buildColumns(fields);
}
},
onGroupChanged: (groups) {},
onError: (err) {
Log.error(err);
},
);
}
void _buildColumnItems(List<RowInfo> rowInfos) {
for (final rowInfo in rowInfos) {}
}
void _buildColumns(UnmodifiableListView<FieldPB> fields) {
FieldPB? groupField;
for (final field in fields) {
@ -114,7 +110,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
void _buildColumnsFromSingleSelect(FieldPB field) {
final typeOptionContext = makeTypeOptionContext<SingleSelectTypeOptionPB>(
gridId: _gridDataController.gridId,
gridId: _dataController.gridId,
field: field,
);
@ -135,7 +131,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
}
Future<void> _loadGrid(Emitter<BoardState> emit) async {
final result = await _gridDataController.loadData();
final result = await _dataController.loadData();
result.fold(
(grid) => emit(
state.copyWith(loadingState: GridLoadingState.finish(left(unit))),

View File

@ -1,121 +1,113 @@
// import 'dart:collection';
import 'dart:collection';
// import 'package:flowy_sdk/log.dart';
// import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
// import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
// import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.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 'dart:async';
// import 'package:dartz/dartz.dart';
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
// typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldPB>);
// typedef OnGridChanged = void Function(GridPB);
typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldPB>);
typedef OnGridChanged = void Function(GridPB);
typedef OnGroupChanged = void Function(List<GroupPB>);
typedef OnError = void Function(FlowyError);
class BoardDataController {
final String gridId;
final GridService _gridFFIService;
final GridFieldCache fieldCache;
// class ridDataController {
// final String gridId;
// final GridService _gridFFIService;
// final GridFieldCache fieldCache;
// key: the block id
final LinkedHashMap<String, GridBlockCache> _blocks;
UnmodifiableMapView<String, GridBlockCache> get blocks =>
UnmodifiableMapView(_blocks);
// // key: the block id
// final LinkedHashMap<String, GridBlockCache> _blocks;
// UnmodifiableMapView<String, GridBlockCache> get blocks =>
// UnmodifiableMapView(_blocks);
OnFieldsChanged? _onFieldsChanged;
OnGridChanged? _onGridChanged;
OnGroupChanged? _onGroupChanged;
OnError? _onError;
// OnRowsChanged? _onRowChanged;
// OnFieldsChanged? _onFieldsChanged;
// OnGridChanged? _onGridChanged;
BoardDataController({required ViewPB view})
: gridId = view.id,
_blocks = LinkedHashMap.identity(),
_gridFFIService = GridService(gridId: view.id),
fieldCache = GridFieldCache(gridId: view.id);
// List<GridRowInfo> get rowInfos {
// final List<GridRowInfo> rows = [];
// for (var block in _blocks.values) {
// rows.addAll(block.rows);
// }
// return rows;
// }
void addListener({
OnGridChanged? onGridChanged,
OnFieldsChanged? onFieldsChanged,
OnGroupChanged? onGroupChanged,
OnError? onError,
}) {
_onGridChanged = onGridChanged;
_onFieldsChanged = onFieldsChanged;
_onGroupChanged = onGroupChanged;
_onError = onError;
// GridDataController({required ViewPB view})
// : gridId = view.id,
// _blocks = LinkedHashMap.identity(),
// _gridFFIService = GridService(gridId: view.id),
// fieldCache = GridFieldCache(gridId: view.id);
fieldCache.addListener(onFields: (fields) {
_onFieldsChanged?.call(UnmodifiableListView(fields));
});
}
// void addListener({
// required OnGridChanged onGridChanged,
// required OnRowsChanged onRowsChanged,
// required OnFieldsChanged onFieldsChanged,
// }) {
// _onGridChanged = onGridChanged;
// _onRowChanged = onRowsChanged;
// _onFieldsChanged = onFieldsChanged;
Future<Either<Unit, FlowyError>> loadData() async {
final result = await _gridFFIService.loadGrid();
return Future(
() => result.fold(
(grid) async {
_onGridChanged?.call(grid);
return await _loadFields(grid).then((result) {
return result.fold(
(l) {
_loadGroups();
return left(l);
},
(err) => right(err),
);
});
},
(err) => right(err),
),
);
}
// fieldCache.addListener(onFields: (fields) {
// _onFieldsChanged?.call(UnmodifiableListView(fields));
// });
// }
void createRow() {
_gridFFIService.createRow();
}
// Future<Either<Unit, FlowyError>> loadData() async {
// final result = await _gridFFIService.loadGrid();
// return Future(
// () => result.fold(
// (grid) async {
// _initialBlocks(grid.blocks);
// _onGridChanged?.call(grid);
// return await _loadFields(grid);
// },
// (err) => right(err),
// ),
// );
// }
Future<void> dispose() async {
await _gridFFIService.closeGrid();
await fieldCache.dispose();
// void createRow() {
// _gridFFIService.createRow();
// }
for (final blockCache in _blocks.values) {
blockCache.dispose();
}
}
// Future<void> dispose() async {
// await _gridFFIService.closeGrid();
// await fieldCache.dispose();
Future<Either<Unit, FlowyError>> _loadFields(GridPB grid) async {
final result = await _gridFFIService.getFields(fieldIds: grid.fields);
return Future(
() => result.fold(
(fields) {
fieldCache.fields = fields.items;
_onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields));
return left(unit);
},
(err) => right(err),
),
);
}
// for (final blockCache in _blocks.values) {
// blockCache.dispose();
// }
// }
// void _initialBlocks(List<BlockPB> blocks) {
// for (final block in blocks) {
// if (_blocks[block.id] != null) {
// Log.warn("Initial duplicate block's cache: ${block.id}");
// return;
// }
// final cache = GridBlockCache(
// gridId: gridId,
// block: block,
// fieldCache: fieldCache,
// );
// cache.addListener(
// onChangeReason: (reason) {
// _onRowChanged?.call(rowInfos, reason);
// },
// );
// _blocks[block.id] = cache;
// }
// }
// Future<Either<Unit, FlowyError>> _loadFields(GridPB grid) async {
// final result = await _gridFFIService.getFields(fieldIds: grid.fields);
// return Future(
// () => result.fold(
// (fields) {
// fieldCache.fields = fields.items;
// _onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields));
// return left(unit);
// },
// (err) => right(err),
// ),
// );
// }
// }
Future<void> _loadGroups() async {
final result = await _gridFFIService.loadGroups();
return Future(
() => result.fold(
(groups) {
_onGroupChanged?.call(groups.items);
},
(err) => _onError?.call(err),
),
);
}
}

View File

@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder {
class BoardPluginConfig implements PluginConfig {
@override
bool get creatable => true;
bool get creatable => false;
}
class BoardPlugin extends Plugin {

View File

@ -8,6 +8,6 @@ class BoardCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(child: Text('1234'));
return const Text('1234');
}
}

View File

@ -1,13 +1,10 @@
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),

View File

@ -75,7 +75,7 @@ class SelectOptionTypeOptionState with _$SelectOptionTypeOptionState {
required List<SelectOptionPB> options,
required bool isEditingOption,
required Option<String> newOptionName,
}) = _SelectOptionTyepOptionState;
}) = _SelectOptionTypeOptionState;
factory SelectOptionTypeOptionState.initial(List<SelectOptionPB> options) =>
SelectOptionTypeOptionState(

View File

@ -20,7 +20,7 @@ typedef OnRowsChanged = void Function(
List<RowInfo> rowInfos,
RowChangeReason,
);
typedef ListenONRowChangedCondition = bool Function();
typedef ListenOnRowChangedCondition = bool Function();
class GridDataController {
final String gridId;

View File

@ -5,6 +5,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.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:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
class GridService {
@ -38,4 +39,9 @@ class GridService {
final request = ViewIdPB(value: gridId);
return FolderEventCloseView(request).send();
}
Future<Either<RepeatedGridGroupPB, FlowyError>> loadGroups() {
final payload = GridIdPB(value: gridId);
return GridEventGetGroup(payload).send();
}
}

View File

@ -1,6 +1,5 @@
import 'dart:typed_data';
import 'package:app_flowy/plugins/grid/application/field/type_option/multi_select_type_option.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';
@ -11,7 +10,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart'
import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
import 'package:protobuf/protobuf.dart';
import 'package:app_flowy/plugins/grid/application/prelude.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter/material.dart';
import 'checkbox.dart';

View File

@ -1,5 +1,5 @@
pub use crate::entities::view::ViewDataTypePB;
use crate::entities::{SubViewDataTypePB, ViewInfoPB};
use crate::entities::ViewInfoPB;
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
use crate::{
dart_notification::{send_dart_notification, FolderNotification},

View File

@ -359,6 +359,7 @@ pub async fn create_view(
desc: desc.to_string(),
thumbnail: None,
data_type,
sub_data_type: None,
plugin_type: 0,
data: vec![],
};

View File

@ -32,7 +32,7 @@ impl std::convert::From<&GridGroupRevision> for GridGroupConfigurationPB {
#[derive(ProtoBuf, Debug, Default, Clone)]
pub struct RepeatedGridGroupPB {
#[pb(index = 1)]
groups: Vec<GroupPB>,
items: Vec<GroupPB>,
}
#[derive(ProtoBuf, Debug, Default, Clone)]

View File

@ -6,7 +6,7 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode;
use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::GridLayoutRevision;
use flowy_sync::entities::grid::{DeleteGroupParams, GridSettingChangesetParams};
use flowy_sync::entities::grid::GridSettingChangesetParams;
use std::collections::HashMap;
use std::convert::TryInto;
use strum::IntoEnumIterator;

View File

@ -35,6 +35,8 @@ pub struct GridRevisionEditor {
block_manager: Arc<GridBlockManager>,
#[allow(dead_code)]
pub(crate) filter_service: Arc<GridFilterService>,
#[allow(dead_code)]
pub(crate) group_service: Arc<GridGroupService>,
}

View File

@ -5,8 +5,11 @@ use std::sync::Arc;
use tokio::sync::RwLock;
pub(crate) struct GridGroupService {
#[allow(dead_code)]
scheduler: Arc<dyn GridServiceTaskScheduler>,
#[allow(dead_code)]
grid_pad: Arc<RwLock<GridRevisionPad>>,
#[allow(dead_code)]
block_manager: Arc<GridBlockManager>,
}

View File

@ -1,3 +1,3 @@
mod group_service;
pub use group_service::*;
pub(crate) use group_service::*;

View File

@ -50,18 +50,16 @@ impl<'a> RowRevisionBuilder<'a> {
}
}
pub fn insert_select_option_cell(mut self, field_id: &str, data: String) -> Self {
pub fn insert_select_option_cell(&mut self, field_id: &str, data: String) {
match self.field_rev_map.get(&field_id.to_owned()) {
None => {
tracing::warn!("Invalid field_id: {}", field_id);
self
}
Some(field_rev) => {
let cell_data = SelectOptionCellChangeset::from_insert(&data).to_str();
let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap();
let cell = CellRevision::new(data);
self.payload.cell_by_field_id.insert(field_id.to_owned(), cell);
self
}
}
}

View File

@ -48,19 +48,18 @@ pub fn make_default_board() -> BuildGridContext {
let done_option = SelectOptionPB::new("Done");
let single_select = SingleSelectTypeOptionBuilder::default()
.add_option(not_started_option.clone())
.add_option(in_progress_option.clone())
.add_option(done_option.clone());
.add_option(in_progress_option)
.add_option(done_option);
let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
let single_select_field_id = single_select_field.id.clone();
grid_builder.add_field(single_select_field);
// rows
// Insert rows
for _ in 0..3 {
grid_builder.add_row(
RowRevisionBuilder::new(grid_builder.block_id(), grid_builder.field_revs())
.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone())
.build(),
);
let mut row_builder = RowRevisionBuilder::new(grid_builder.block_id(), grid_builder.field_revs());
row_builder.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone());
let row = row_builder.build();
grid_builder.add_row(row);
}
grid_builder.build()

View File

@ -10,7 +10,6 @@ use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
use strum::EnumCount;
pub struct GridRowTestBuilder<'a> {
block_id: String,
field_revs: &'a [Arc<FieldRevision>],
inner_builder: RowRevisionBuilder<'a>,
}
@ -20,7 +19,6 @@ impl<'a> GridRowTestBuilder<'a> {
assert_eq!(field_revs.len(), FieldType::COUNT);
let inner_builder = RowRevisionBuilder::new(block_id, field_revs);
Self {
block_id: block_id.to_owned(),
field_revs,
inner_builder,
}