mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: refactor cell context
This commit is contained in:
parent
ec16fbe551
commit
be49784f5a
@ -16,8 +16,10 @@ import 'package:app_flowy/user/presentation/router.dart';
|
|||||||
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
|
||||||
@ -174,25 +176,25 @@ void _resolveGridDeps(GetIt getIt) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<SelectionCellBloc, GridCellContext, void>(
|
getIt.registerFactoryParam<SelectionCellBloc, GridCellContext<SelectOptionContext>, void>(
|
||||||
(context, _) => SelectionCellBloc(
|
(context, _) => SelectionCellBloc(
|
||||||
cellContext: context,
|
cellContext: context,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<NumberCellBloc, GridCellContext, void>(
|
getIt.registerFactoryParam<NumberCellBloc, GridCellContext<Cell>, void>(
|
||||||
(context, _) => NumberCellBloc(
|
(context, _) => NumberCellBloc(
|
||||||
cellContext: context,
|
cellContext: context,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<DateCellBloc, GridCellContext, void>(
|
getIt.registerFactoryParam<DateCellBloc, GridCellContext<Cell>, void>(
|
||||||
(context, _) => DateCellBloc(
|
(context, _) => DateCellBloc(
|
||||||
cellContext: context,
|
cellContext: context,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<CheckboxCellBloc, GridCellContext, void>(
|
getIt.registerFactoryParam<CheckboxCellBloc, GridCellContext<Cell>, void>(
|
||||||
(cellData, _) => CheckboxCellBloc(
|
(cellData, _) => CheckboxCellBloc(
|
||||||
service: CellService(),
|
service: CellService(),
|
||||||
cellContext: cellData,
|
cellContext: cellData,
|
||||||
|
@ -9,55 +9,126 @@ import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
||||||
|
|
||||||
part 'cell_service.freezed.dart';
|
part 'cell_service.freezed.dart';
|
||||||
|
|
||||||
class GridCellContext {
|
class GridCellContext<T> {
|
||||||
GridCell cellData;
|
final GridCell gridCell;
|
||||||
GridCellCache cellCache;
|
final GridCellCache cellCache;
|
||||||
late GridCellCacheKey _cacheKey;
|
late GridCellCacheKey _cacheKey;
|
||||||
|
final GridCellDataLoader<T> cellDataLoader;
|
||||||
|
|
||||||
|
final CellListener _cellListener;
|
||||||
|
final CellService _cellService = CellService();
|
||||||
|
final ValueNotifier<dynamic> _cellDataNotifier = ValueNotifier(null);
|
||||||
|
|
||||||
GridCellContext({
|
GridCellContext({
|
||||||
required this.cellData,
|
required this.gridCell,
|
||||||
required this.cellCache,
|
required this.cellCache,
|
||||||
}) {
|
required this.cellDataLoader,
|
||||||
|
}) : _cellListener = CellListener(rowId: gridCell.rowId, fieldId: gridCell.field.id) {
|
||||||
|
_cellListener.updateCellNotifier?.addPublishListener((result) {
|
||||||
|
result.fold(
|
||||||
|
(notification) => _loadData(),
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
_cellListener.start();
|
||||||
|
|
||||||
_cacheKey = GridCellCacheKey(
|
_cacheKey = GridCellCacheKey(
|
||||||
objectId: "$hashCode",
|
objectId: "$hashCode",
|
||||||
fieldId: cellData.field.id,
|
fieldId: gridCell.field.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get gridId => cellData.gridId;
|
String get gridId => gridCell.gridId;
|
||||||
|
|
||||||
String get cellId => cellData.rowId + (cellData.cell?.fieldId ?? "");
|
String get rowId => gridCell.rowId;
|
||||||
|
|
||||||
String get rowId => cellData.rowId;
|
String get cellId => gridCell.rowId + gridCell.field.id;
|
||||||
|
|
||||||
String get fieldId => cellData.field.id;
|
String get fieldId => gridCell.field.id;
|
||||||
|
|
||||||
FieldType get fieldType => cellData.field.fieldType;
|
Field get field => gridCell.field;
|
||||||
|
|
||||||
Field get field => cellData.field;
|
FieldType get fieldType => gridCell.field.fieldType;
|
||||||
|
|
||||||
GridCellCacheKey get cacheKey => _cacheKey;
|
GridCellCacheKey get cacheKey => _cacheKey;
|
||||||
|
|
||||||
T? getCacheData<T>() {
|
T? getCellData() {
|
||||||
return cellCache.get(cacheKey);
|
final data = cellCache.get(cacheKey);
|
||||||
|
if (data == null) {
|
||||||
|
_loadData();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCacheData(dynamic data) {
|
void setCellData(T? data) {
|
||||||
cellCache.insert(GridCellCacheData(key: cacheKey, object: data));
|
cellCache.insert(GridCellCacheData(key: cacheKey, object: data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveCellData(String data) {
|
||||||
|
_cellService.updateCell(gridId: gridId, fieldId: field.id, rowId: rowId, data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _loadData() {
|
||||||
|
// It may trigger getCell multiple times. Use cancel operation to fix this.
|
||||||
|
cellDataLoader.loadData().then((data) {
|
||||||
|
_cellDataNotifier.value = data;
|
||||||
|
setCellData(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void onFieldChanged(VoidCallback callback) {
|
void onFieldChanged(VoidCallback callback) {
|
||||||
cellCache.addListener(cacheKey, callback);
|
cellCache.addListener(cacheKey, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onCellChanged(void Function(T) callback) {
|
||||||
|
_cellDataNotifier.addListener(() {
|
||||||
|
final value = _cellDataNotifier.value;
|
||||||
|
if (value is T) {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void removeListener() {
|
void removeListener() {
|
||||||
cellCache.removeListener(cacheKey);
|
cellCache.removeListener(cacheKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class GridCellDataLoader<T> {
|
||||||
|
Future<T?> loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultCellDataLoader implements GridCellDataLoader<Cell> {
|
||||||
|
final CellService service = CellService();
|
||||||
|
final GridCell gridCell;
|
||||||
|
|
||||||
|
DefaultCellDataLoader({
|
||||||
|
required this.gridCell,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Cell?> loadData() {
|
||||||
|
final fut = service.getCell(
|
||||||
|
gridId: gridCell.gridId,
|
||||||
|
fieldId: gridCell.field.id,
|
||||||
|
rowId: gridCell.rowId,
|
||||||
|
);
|
||||||
|
return fut.then((result) {
|
||||||
|
return result.fold((data) => data, (err) {
|
||||||
|
Log.error(err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// key: rowId
|
// key: rowId
|
||||||
typedef CellDataMap = LinkedHashMap<String, GridCell>;
|
typedef GridCellMap = LinkedHashMap<String, GridCell>;
|
||||||
|
|
||||||
class GridCellCacheData {
|
class GridCellCacheData {
|
||||||
GridCellCacheKey key;
|
GridCellCacheKey key;
|
||||||
@ -175,41 +246,41 @@ class CellService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CellCache {
|
// class CellCache {
|
||||||
final CellService _cellService;
|
// final CellService _cellService;
|
||||||
final HashMap<String, Cell> _cellDataMap = HashMap();
|
// final HashMap<String, Cell> _cellDataMap = HashMap();
|
||||||
|
|
||||||
CellCache() : _cellService = CellService();
|
// CellCache() : _cellService = CellService();
|
||||||
|
|
||||||
Future<Option<Cell>> getCellData(GridCell identifier) async {
|
// Future<Option<Cell>> getCellData(GridCell identifier) async {
|
||||||
final cellId = _cellId(identifier);
|
// final cellId = _cellId(identifier);
|
||||||
final Cell? data = _cellDataMap[cellId];
|
// final Cell? data = _cellDataMap[cellId];
|
||||||
if (data != null) {
|
// if (data != null) {
|
||||||
return Future(() => Some(data));
|
// return Future(() => Some(data));
|
||||||
}
|
// }
|
||||||
|
|
||||||
final result = await _cellService.getCell(
|
// final result = await _cellService.getCell(
|
||||||
gridId: identifier.gridId,
|
// gridId: identifier.gridId,
|
||||||
fieldId: identifier.field.id,
|
// fieldId: identifier.field.id,
|
||||||
rowId: identifier.rowId,
|
// rowId: identifier.rowId,
|
||||||
);
|
// );
|
||||||
|
|
||||||
return result.fold(
|
// return result.fold(
|
||||||
(cell) {
|
// (cell) {
|
||||||
_cellDataMap[_cellId(identifier)] = cell;
|
// _cellDataMap[_cellId(identifier)] = cell;
|
||||||
return Some(cell);
|
// return Some(cell);
|
||||||
},
|
// },
|
||||||
(err) {
|
// (err) {
|
||||||
Log.error(err);
|
// Log.error(err);
|
||||||
return none();
|
// return none();
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
String _cellId(GridCell identifier) {
|
// String _cellId(GridCell identifier) {
|
||||||
return "${identifier.rowId}/${identifier.field.id}";
|
// return "${identifier.rowId}/${identifier.field.id}";
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class GridCell with _$GridCell {
|
class GridCell with _$GridCell {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
|
||||||
import 'package:flowy_sdk/log.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
@ -9,15 +7,13 @@ import 'cell_service.dart';
|
|||||||
part 'checkbox_cell_bloc.freezed.dart';
|
part 'checkbox_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
||||||
final CellService _service;
|
final GridCellContext<Cell> _cellContext;
|
||||||
final CellListener _cellListener;
|
|
||||||
|
|
||||||
CheckboxCellBloc({
|
CheckboxCellBloc({
|
||||||
required CellService service,
|
required CellService service,
|
||||||
required GridCellContext cellContext,
|
required GridCellContext<Cell> cellContext,
|
||||||
}) : _service = service,
|
}) : _cellContext = cellContext,
|
||||||
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
|
super(CheckboxCellState.initial(cellContext)) {
|
||||||
super(CheckboxCellState.initial(cellContext.cellData)) {
|
|
||||||
on<CheckboxCellEvent>(
|
on<CheckboxCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
@ -37,42 +33,19 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _cellListener.stop();
|
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_cellListener.updateCellNotifier?.addPublishListener((result) {
|
_cellContext.onCellChanged((cell) {
|
||||||
result.fold(
|
if (!isClosed) {
|
||||||
(notificationData) async => await _loadCellData(),
|
add(CheckboxCellEvent.didReceiveCellUpdate(cell));
|
||||||
(err) => Log.error(err),
|
}
|
||||||
);
|
|
||||||
});
|
});
|
||||||
_cellListener.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _loadCellData() async {
|
|
||||||
final result = await _service.getCell(
|
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
);
|
|
||||||
if (isClosed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result.fold(
|
|
||||||
(cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)),
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateCellData() {
|
void _updateCellData() {
|
||||||
_service.updateCell(
|
_cellContext.saveCellData(!state.isSelected ? "Yes" : "No");
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
data: !state.isSelected ? "Yes" : "No",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,12 +59,11 @@ class CheckboxCellEvent with _$CheckboxCellEvent {
|
|||||||
@freezed
|
@freezed
|
||||||
class CheckboxCellState with _$CheckboxCellState {
|
class CheckboxCellState with _$CheckboxCellState {
|
||||||
const factory CheckboxCellState({
|
const factory CheckboxCellState({
|
||||||
required GridCell cellData,
|
|
||||||
required bool isSelected,
|
required bool isSelected,
|
||||||
}) = _CheckboxCellState;
|
}) = _CheckboxCellState;
|
||||||
|
|
||||||
factory CheckboxCellState.initial(GridCell cellData) {
|
factory CheckboxCellState.initial(GridCellContext context) {
|
||||||
return CheckboxCellState(cellData: cellData, isSelected: _isSelected(cellData.cell));
|
return CheckboxCellState(isSelected: _isSelected(context.getCellData()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, Field;
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, Field;
|
||||||
@ -10,15 +9,12 @@ import 'cell_service.dart';
|
|||||||
part 'date_cell_bloc.freezed.dart';
|
part 'date_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||||
final CellService _service;
|
|
||||||
final CellListener _cellListener;
|
|
||||||
final SingleFieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
|
final GridCellContext<Cell> cellContext;
|
||||||
|
|
||||||
DateCellBloc({required GridCellContext cellContext})
|
DateCellBloc({required this.cellContext})
|
||||||
: _service = CellService(),
|
: _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
||||||
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
|
super(DateCellState.initial(cellContext)) {
|
||||||
_fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
|
||||||
super(DateCellState.initial(cellContext.cellData)) {
|
|
||||||
on<DateCellEvent>(
|
on<DateCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.map(
|
event.map(
|
||||||
@ -30,13 +26,11 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
|||||||
},
|
},
|
||||||
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
|
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
cellData: state.cellData.copyWith(cell: value.cell),
|
|
||||||
content: value.cell.content,
|
content: value.cell.content,
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
||||||
emit(state.copyWith(field: value.field));
|
emit(state.copyWith(field: value.field));
|
||||||
_loadCellData();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -45,19 +39,16 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _cellListener.stop();
|
|
||||||
await _fieldListener.stop();
|
await _fieldListener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_cellListener.updateCellNotifier?.addPublishListener((result) {
|
cellContext.onCellChanged((cell) {
|
||||||
result.fold(
|
if (!isClosed) {
|
||||||
(notificationData) => _loadCellData(),
|
add(DateCellEvent.didReceiveCellUpdate(cell));
|
||||||
(err) => Log.error(err),
|
}
|
||||||
);
|
});
|
||||||
}, listenWhen: () => !isClosed);
|
|
||||||
_cellListener.start();
|
|
||||||
|
|
||||||
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
@ -68,29 +59,9 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
|||||||
_fieldListener.start();
|
_fieldListener.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadCellData() async {
|
|
||||||
final result = await _service.getCell(
|
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
);
|
|
||||||
if (isClosed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result.fold(
|
|
||||||
(cell) => add(DateCellEvent.didReceiveCellUpdate(cell)),
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _updateCellData(DateTime day) {
|
void _updateCellData(DateTime day) {
|
||||||
final data = day.millisecondsSinceEpoch ~/ 1000;
|
final data = day.millisecondsSinceEpoch ~/ 1000;
|
||||||
_service.updateCell(
|
cellContext.saveCellData(data.toString());
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
data: data.toString(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,15 +76,13 @@ class DateCellEvent with _$DateCellEvent {
|
|||||||
@freezed
|
@freezed
|
||||||
class DateCellState with _$DateCellState {
|
class DateCellState with _$DateCellState {
|
||||||
const factory DateCellState({
|
const factory DateCellState({
|
||||||
required GridCell cellData,
|
|
||||||
required String content,
|
required String content,
|
||||||
required Field field,
|
required Field field,
|
||||||
DateTime? selectedDay,
|
DateTime? selectedDay,
|
||||||
}) = _DateCellState;
|
}) = _DateCellState;
|
||||||
|
|
||||||
factory DateCellState.initial(GridCell cellData) => DateCellState(
|
factory DateCellState.initial(GridCellContext context) => DateCellState(
|
||||||
cellData: cellData,
|
field: context.field,
|
||||||
field: cellData.field,
|
content: context.getCellData()?.content ?? "",
|
||||||
content: cellData.cell?.content ?? "",
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
@ -10,16 +9,13 @@ import 'cell_service.dart';
|
|||||||
part 'number_cell_bloc.freezed.dart';
|
part 'number_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
||||||
final CellService _service;
|
final GridCellContext<Cell> cellContext;
|
||||||
final CellListener _cellListener;
|
|
||||||
final SingleFieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
|
|
||||||
NumberCellBloc({
|
NumberCellBloc({
|
||||||
required GridCellContext cellContext,
|
required this.cellContext,
|
||||||
}) : _service = CellService(),
|
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
||||||
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
|
super(NumberCellState.initial(cellContext)) {
|
||||||
_fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
|
||||||
super(NumberCellState.initial(cellContext.cellData)) {
|
|
||||||
on<NumberCellEvent>(
|
on<NumberCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
@ -38,60 +34,31 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateCellValue(_UpdateCell value, Emitter<NumberCellState> emit) async {
|
Future<void> _updateCellValue(_UpdateCell value, Emitter<NumberCellState> emit) async {
|
||||||
final result = await _service.updateCell(
|
cellContext.saveCellData(value.text);
|
||||||
gridId: state.cellData.gridId,
|
cellContext.reloadCellData();
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
data: value.text,
|
|
||||||
);
|
|
||||||
result.fold(
|
|
||||||
(field) => _getCellData(),
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _cellListener.stop();
|
|
||||||
await _fieldListener.stop();
|
await _fieldListener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_cellListener.updateCellNotifier?.addPublishListener((result) {
|
cellContext.onCellChanged((cell) {
|
||||||
result.fold(
|
if (!isClosed) {
|
||||||
(notificationData) async {
|
add(NumberCellEvent.didReceiveCellUpdate(cell));
|
||||||
await _getCellData();
|
}
|
||||||
},
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
_cellListener.start();
|
|
||||||
|
|
||||||
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(field) => _getCellData(),
|
(field) => cellContext.reloadCellData(),
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
_fieldListener.start();
|
_fieldListener.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _getCellData() async {
|
|
||||||
final result = await _service.getCell(
|
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isClosed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result.fold(
|
|
||||||
(cell) => add(NumberCellEvent.didReceiveCellUpdate(cell)),
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -104,11 +71,10 @@ class NumberCellEvent with _$NumberCellEvent {
|
|||||||
@freezed
|
@freezed
|
||||||
class NumberCellState with _$NumberCellState {
|
class NumberCellState with _$NumberCellState {
|
||||||
const factory NumberCellState({
|
const factory NumberCellState({
|
||||||
required GridCell cellData,
|
|
||||||
required String content,
|
required String content,
|
||||||
}) = _NumberCellState;
|
}) = _NumberCellState;
|
||||||
|
|
||||||
factory NumberCellState.initial(GridCell cellData) {
|
factory NumberCellState.initial(GridCellContext context) {
|
||||||
return NumberCellState(cellData: cellData, content: cellData.cell?.content ?? "");
|
return NumberCellState(content: context.getCellData().cell?.content ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,43 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flowy_sdk/dispatch/dispatch.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/cell_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
|
|
||||||
class SelectOptionService {
|
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
|
||||||
SelectOptionService();
|
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> create({
|
import 'cell_service.dart';
|
||||||
required String gridId,
|
|
||||||
required String fieldId,
|
class SelectOptionCellDataLoader implements GridCellDataLoader<SelectOptionContext> {
|
||||||
required String rowId,
|
final SelectOptionService service;
|
||||||
required String name,
|
final GridCell gridCell;
|
||||||
}) {
|
SelectOptionCellDataLoader({
|
||||||
|
required this.gridCell,
|
||||||
|
}) : service = SelectOptionService(gridCell: gridCell);
|
||||||
|
@override
|
||||||
|
Future<SelectOptionContext?> loadData() async {
|
||||||
|
return service.getOpitonContext().then((result) {
|
||||||
|
return result.fold(
|
||||||
|
(data) => data,
|
||||||
|
(err) {
|
||||||
|
Log.error(err);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectOptionService {
|
||||||
|
final GridCell gridCell;
|
||||||
|
SelectOptionService({required this.gridCell});
|
||||||
|
|
||||||
|
String get gridId => gridCell.gridId;
|
||||||
|
String get fieldId => gridCell.field.id;
|
||||||
|
String get rowId => gridCell.rowId;
|
||||||
|
|
||||||
|
Future<Either<Unit, FlowyError>> create({required String name}) {
|
||||||
return TypeOptionService(gridId: gridId, fieldId: fieldId).newOption(name: name).then(
|
return TypeOptionService(gridId: gridId, fieldId: fieldId).newOption(name: name).then(
|
||||||
(result) {
|
(result) {
|
||||||
return result.fold(
|
return result.fold(
|
||||||
@ -34,9 +58,6 @@ class SelectOptionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> update({
|
Future<Either<Unit, FlowyError>> update({
|
||||||
required String gridId,
|
|
||||||
required String fieldId,
|
|
||||||
required String rowId,
|
|
||||||
required SelectOption option,
|
required SelectOption option,
|
||||||
}) {
|
}) {
|
||||||
final cellIdentifier = CellIdentifierPayload.create()
|
final cellIdentifier = CellIdentifierPayload.create()
|
||||||
@ -50,9 +71,6 @@ class SelectOptionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> delete({
|
Future<Either<Unit, FlowyError>> delete({
|
||||||
required String gridId,
|
|
||||||
required String fieldId,
|
|
||||||
required String rowId,
|
|
||||||
required SelectOption option,
|
required SelectOption option,
|
||||||
}) {
|
}) {
|
||||||
final cellIdentifier = CellIdentifierPayload.create()
|
final cellIdentifier = CellIdentifierPayload.create()
|
||||||
@ -67,11 +85,7 @@ class SelectOptionService {
|
|||||||
return GridEventUpdateSelectOption(payload).send();
|
return GridEventUpdateSelectOption(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<SelectOptionContext, FlowyError>> getOpitonContext({
|
Future<Either<SelectOptionContext, FlowyError>> getOpitonContext() {
|
||||||
required String gridId,
|
|
||||||
required String fieldId,
|
|
||||||
required String rowId,
|
|
||||||
}) {
|
|
||||||
final payload = CellIdentifierPayload.create()
|
final payload = CellIdentifierPayload.create()
|
||||||
..gridId = gridId
|
..gridId = gridId
|
||||||
..fieldId = fieldId
|
..fieldId = fieldId
|
||||||
@ -80,12 +94,7 @@ class SelectOptionService {
|
|||||||
return GridEventGetSelectOptionContext(payload).send();
|
return GridEventGetSelectOptionContext(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<void, FlowyError>> select({
|
Future<Either<void, FlowyError>> select({required String optionId}) {
|
||||||
required String gridId,
|
|
||||||
required String fieldId,
|
|
||||||
required String rowId,
|
|
||||||
required String optionId,
|
|
||||||
}) {
|
|
||||||
final payload = SelectOptionCellChangesetPayload.create()
|
final payload = SelectOptionCellChangesetPayload.create()
|
||||||
..gridId = gridId
|
..gridId = gridId
|
||||||
..fieldId = fieldId
|
..fieldId = fieldId
|
||||||
@ -94,12 +103,7 @@ class SelectOptionService {
|
|||||||
return GridEventUpdateCellSelectOption(payload).send();
|
return GridEventUpdateCellSelectOption(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<void, FlowyError>> unSelect({
|
Future<Either<void, FlowyError>> unSelect({required String optionId}) {
|
||||||
required String gridId,
|
|
||||||
required String fieldId,
|
|
||||||
required String rowId,
|
|
||||||
required String optionId,
|
|
||||||
}) {
|
|
||||||
final payload = SelectOptionCellChangesetPayload.create()
|
final payload = SelectOptionCellChangesetPayload.create()
|
||||||
..gridId = gridId
|
..gridId = gridId
|
||||||
..fieldId = fieldId
|
..fieldId = fieldId
|
||||||
|
@ -1,39 +1,31 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flowy_sdk/log.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
|
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
||||||
|
|
||||||
part 'selection_cell_bloc.freezed.dart';
|
part 'selection_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||||
final SelectOptionService _service;
|
|
||||||
final CellListener _cellListener;
|
|
||||||
final SingleFieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
final GridCellContext _cellContext;
|
final GridCellContext<SelectOptionContext> cellContext;
|
||||||
|
|
||||||
SelectionCellBloc({
|
SelectionCellBloc({
|
||||||
required GridCellContext cellContext,
|
required this.cellContext,
|
||||||
}) : _service = SelectOptionService(),
|
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
||||||
_cellContext = cellContext,
|
super(SelectionCellState.initial(cellContext)) {
|
||||||
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
|
|
||||||
_fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
|
||||||
super(SelectionCellState.initial(cellContext.cellData)) {
|
|
||||||
on<SelectionCellEvent>(
|
on<SelectionCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
initial: (_InitialCell value) async {
|
initial: (_InitialCell value) async {
|
||||||
_startListening();
|
_startListening();
|
||||||
_loadOptions();
|
|
||||||
},
|
},
|
||||||
didReceiveOptions: (_DidReceiveOptions value) {
|
didReceiveOptions: (_DidReceiveOptions value) {
|
||||||
emit(state.copyWith(options: value.options, selectedOptions: value.selectedOptions));
|
emit(state.copyWith(
|
||||||
|
options: value.options,
|
||||||
|
selectedOptions: value.selectedOptions,
|
||||||
|
));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -42,57 +34,22 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _cellListener.stop();
|
|
||||||
await _fieldListener.stop();
|
await _fieldListener.stop();
|
||||||
_cellContext.removeListener();
|
cellContext.removeListener();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loadOptions() async {
|
|
||||||
var selectOptionContext = _cellContext.getCacheData<SelectOptionContext>();
|
|
||||||
if (selectOptionContext == null) {
|
|
||||||
final result = await _service.getOpitonContext(
|
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
);
|
|
||||||
if (isClosed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.fold(
|
|
||||||
(newSelectOptionContext) {
|
|
||||||
_cellContext.setCacheData(newSelectOptionContext);
|
|
||||||
selectOptionContext = newSelectOptionContext;
|
|
||||||
},
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(SelectionCellEvent.didReceiveOptions(
|
|
||||||
selectOptionContext!.options,
|
|
||||||
selectOptionContext!.selectOptions,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_cellListener.updateCellNotifier?.addPublishListener((result) {
|
cellContext.onCellChanged((selectOptionContext) {
|
||||||
result.fold(
|
if (!isClosed) {
|
||||||
(notificationData) => _loadOptions(),
|
add(SelectionCellEvent.didReceiveOptions(
|
||||||
(err) => Log.error(err),
|
selectOptionContext.options,
|
||||||
);
|
selectOptionContext.selectOptions,
|
||||||
|
));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
_cellListener.start();
|
|
||||||
|
|
||||||
_cellContext.onFieldChanged(() => _loadOptions());
|
cellContext.onFieldChanged(() => cellContext.reloadCellData());
|
||||||
|
|
||||||
// _fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
|
||||||
// result.fold(
|
|
||||||
// (field) => _loadOptions(),
|
|
||||||
// (err) => Log.error(err),
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
// _fieldListener.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,14 +65,16 @@ class SelectionCellEvent with _$SelectionCellEvent {
|
|||||||
@freezed
|
@freezed
|
||||||
class SelectionCellState with _$SelectionCellState {
|
class SelectionCellState with _$SelectionCellState {
|
||||||
const factory SelectionCellState({
|
const factory SelectionCellState({
|
||||||
required GridCell cellData,
|
|
||||||
required List<SelectOption> options,
|
required List<SelectOption> options,
|
||||||
required List<SelectOption> selectedOptions,
|
required List<SelectOption> selectedOptions,
|
||||||
}) = _SelectionCellState;
|
}) = _SelectionCellState;
|
||||||
|
|
||||||
factory SelectionCellState.initial(GridCell cellData) => SelectionCellState(
|
factory SelectionCellState.initial(GridCellContext<SelectOptionContext> context) {
|
||||||
cellData: cellData,
|
final data = context.getCellData();
|
||||||
options: [],
|
|
||||||
selectedOptions: [],
|
return SelectionCellState(
|
||||||
);
|
options: data?.options ?? [],
|
||||||
|
selectedOptions: data?.selectOptions ?? [],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,28 +13,19 @@ part 'selection_editor_bloc.freezed.dart';
|
|||||||
|
|
||||||
class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
|
class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
|
||||||
final SelectOptionService _selectOptionService;
|
final SelectOptionService _selectOptionService;
|
||||||
final SingleFieldListener _fieldListener;
|
final GridCellContext<SelectOptionContext> cellContext;
|
||||||
final CellListener _cellListener;
|
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
SelectOptionEditorBloc({
|
SelectOptionEditorBloc({
|
||||||
required GridCell cellData,
|
required this.cellContext,
|
||||||
required List<SelectOption> options,
|
}) : _selectOptionService = SelectOptionService(gridCell: cellContext.gridCell),
|
||||||
required List<SelectOption> selectedOptions,
|
super(SelectOptionEditorState.initial(cellContext)) {
|
||||||
}) : _selectOptionService = SelectOptionService(),
|
|
||||||
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
|
||||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
|
||||||
super(SelectOptionEditorState.initial(cellData, options, selectedOptions)) {
|
|
||||||
on<SelectOptionEditorEvent>(
|
on<SelectOptionEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
initial: (_Initial value) async {
|
initial: (_Initial value) async {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
|
||||||
emit(state.copyWith(field: value.field));
|
|
||||||
_loadOptions();
|
|
||||||
},
|
|
||||||
didReceiveOptions: (_DidReceiveOptions value) {
|
didReceiveOptions: (_DidReceiveOptions value) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
options: value.options,
|
options: value.options,
|
||||||
@ -61,26 +52,17 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
|||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
_delayOperation?.cancel();
|
_delayOperation?.cancel();
|
||||||
await _fieldListener.stop();
|
cellContext.removeListener();
|
||||||
await _cellListener.stop();
|
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _createOption(String name) async {
|
void _createOption(String name) async {
|
||||||
final result = await _selectOptionService.create(
|
final result = await _selectOptionService.create(name: name);
|
||||||
gridId: state.gridId,
|
result.fold((l) => {}, (err) => Log.error(err));
|
||||||
fieldId: state.field.id,
|
|
||||||
rowId: state.rowId,
|
|
||||||
name: name,
|
|
||||||
);
|
|
||||||
result.fold((l) => _loadOptions(), (err) => Log.error(err));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deleteOption(SelectOption option) async {
|
void _deleteOption(SelectOption option) async {
|
||||||
final result = await _selectOptionService.delete(
|
final result = await _selectOptionService.delete(
|
||||||
gridId: state.gridId,
|
|
||||||
fieldId: state.field.id,
|
|
||||||
rowId: state.rowId,
|
|
||||||
option: option,
|
option: option,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -89,9 +71,6 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
|||||||
|
|
||||||
void _updateOption(SelectOption option) async {
|
void _updateOption(SelectOption option) async {
|
||||||
final result = await _selectOptionService.update(
|
final result = await _selectOptionService.update(
|
||||||
gridId: state.gridId,
|
|
||||||
fieldId: state.field.id,
|
|
||||||
rowId: state.rowId,
|
|
||||||
option: option,
|
option: option,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -101,70 +80,50 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
|||||||
void _onSelectOption(String optionId) {
|
void _onSelectOption(String optionId) {
|
||||||
final hasSelected = state.selectedOptions.firstWhereOrNull((option) => option.id == optionId);
|
final hasSelected = state.selectedOptions.firstWhereOrNull((option) => option.id == optionId);
|
||||||
if (hasSelected != null) {
|
if (hasSelected != null) {
|
||||||
_selectOptionService.unSelect(
|
_selectOptionService.unSelect(optionId: optionId);
|
||||||
gridId: state.gridId,
|
|
||||||
fieldId: state.field.id,
|
|
||||||
rowId: state.rowId,
|
|
||||||
optionId: optionId,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
_selectOptionService.select(
|
_selectOptionService.select(optionId: optionId);
|
||||||
gridId: state.gridId,
|
|
||||||
fieldId: state.field.id,
|
|
||||||
rowId: state.rowId,
|
|
||||||
optionId: optionId,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loadOptions() async {
|
// void _loadOptions() async {
|
||||||
_delayOperation?.cancel();
|
// _delayOperation?.cancel();
|
||||||
_delayOperation = Timer(
|
// _delayOperation = Timer(
|
||||||
const Duration(milliseconds: 1),
|
// const Duration(milliseconds: 1),
|
||||||
() async {
|
// () async {
|
||||||
final result = await _selectOptionService.getOpitonContext(
|
// final result = await _selectOptionService.getOpitonContext();
|
||||||
gridId: state.gridId,
|
// if (isClosed) {
|
||||||
fieldId: state.field.id,
|
// return;
|
||||||
rowId: state.rowId,
|
// }
|
||||||
);
|
|
||||||
if (isClosed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.fold(
|
// result.fold(
|
||||||
(selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions(
|
// (selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions(
|
||||||
selectOptionContext.options,
|
// selectOptionContext.options,
|
||||||
selectOptionContext.selectOptions,
|
// selectOptionContext.selectOptions,
|
||||||
)),
|
// )),
|
||||||
(err) => Log.error(err),
|
// (err) => Log.error(err),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_cellListener.updateCellNotifier?.addPublishListener((result) {
|
cellContext.onCellChanged((selectOptionContext) {
|
||||||
result.fold(
|
if (!isClosed) {
|
||||||
(notificationData) => _loadOptions(),
|
add(SelectOptionEditorEvent.didReceiveOptions(
|
||||||
(err) => Log.error(err),
|
selectOptionContext.options,
|
||||||
);
|
selectOptionContext.selectOptions,
|
||||||
|
));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
_cellListener.start();
|
|
||||||
|
|
||||||
_fieldListener.updateFieldNotifier?.addPublishListener((result) {
|
cellContext.onFieldChanged(() => cellContext.reloadCellData());
|
||||||
result.fold(
|
|
||||||
(field) => add(SelectOptionEditorEvent.didReceiveFieldUpdate(field)),
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
}, listenWhen: () => !isClosed);
|
|
||||||
_fieldListener.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class SelectOptionEditorEvent with _$SelectOptionEditorEvent {
|
class SelectOptionEditorEvent with _$SelectOptionEditorEvent {
|
||||||
const factory SelectOptionEditorEvent.initial() = _Initial;
|
const factory SelectOptionEditorEvent.initial() = _Initial;
|
||||||
const factory SelectOptionEditorEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
|
|
||||||
const factory SelectOptionEditorEvent.didReceiveOptions(
|
const factory SelectOptionEditorEvent.didReceiveOptions(
|
||||||
List<SelectOption> options, List<SelectOption> selectedOptions) = _DidReceiveOptions;
|
List<SelectOption> options, List<SelectOption> selectedOptions) = _DidReceiveOptions;
|
||||||
const factory SelectOptionEditorEvent.newOption(String optionName) = _NewOption;
|
const factory SelectOptionEditorEvent.newOption(String optionName) = _NewOption;
|
||||||
@ -176,24 +135,15 @@ class SelectOptionEditorEvent with _$SelectOptionEditorEvent {
|
|||||||
@freezed
|
@freezed
|
||||||
class SelectOptionEditorState with _$SelectOptionEditorState {
|
class SelectOptionEditorState with _$SelectOptionEditorState {
|
||||||
const factory SelectOptionEditorState({
|
const factory SelectOptionEditorState({
|
||||||
required String gridId,
|
|
||||||
required Field field,
|
|
||||||
required String rowId,
|
|
||||||
required List<SelectOption> options,
|
required List<SelectOption> options,
|
||||||
required List<SelectOption> selectedOptions,
|
required List<SelectOption> selectedOptions,
|
||||||
}) = _SelectOptionEditorState;
|
}) = _SelectOptionEditorState;
|
||||||
|
|
||||||
factory SelectOptionEditorState.initial(
|
factory SelectOptionEditorState.initial(GridCellContext<SelectOptionContext> context) {
|
||||||
GridCell cellData,
|
final data = context.getCellData();
|
||||||
List<SelectOption> options,
|
|
||||||
List<SelectOption> selectedOptions,
|
|
||||||
) {
|
|
||||||
return SelectOptionEditorState(
|
return SelectOptionEditorState(
|
||||||
gridId: cellData.gridId,
|
options: data?.options ?? [],
|
||||||
field: cellData.field,
|
selectedOptions: data?.selectOptions ?? [],
|
||||||
rowId: cellData.rowId,
|
|
||||||
options: options,
|
|
||||||
selectedOptions: selectedOptions,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
|
|||||||
required GridCellContext cellContext,
|
required GridCellContext cellContext,
|
||||||
}) : _service = CellService(),
|
}) : _service = CellService(),
|
||||||
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
|
_cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId),
|
||||||
super(TextCellState.initial(cellContext.cellData)) {
|
super(TextCellState.initial(cellContext.gridCell)) {
|
||||||
on<TextCellEvent>(
|
on<TextCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
|
@ -57,17 +57,17 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
|||||||
class RowEvent with _$RowEvent {
|
class RowEvent with _$RowEvent {
|
||||||
const factory RowEvent.initial() = _InitialRow;
|
const factory RowEvent.initial() = _InitialRow;
|
||||||
const factory RowEvent.createRow() = _CreateRow;
|
const factory RowEvent.createRow() = _CreateRow;
|
||||||
const factory RowEvent.didReceiveCellDatas(CellDataMap cellData) = _DidReceiveCellDatas;
|
const factory RowEvent.didReceiveCellDatas(GridCellMap cellData) = _DidReceiveCellDatas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class RowState with _$RowState {
|
class RowState with _$RowState {
|
||||||
const factory RowState({
|
const factory RowState({
|
||||||
required GridRow rowData,
|
required GridRow rowData,
|
||||||
required CellDataMap cellDataMap,
|
required GridCellMap cellDataMap,
|
||||||
}) = _RowState;
|
}) = _RowState;
|
||||||
|
|
||||||
factory RowState.initial(GridRow rowData, CellDataMap cellDataMap) => RowState(
|
factory RowState.initial(GridRow rowData, GridCellMap cellDataMap) => RowState(
|
||||||
rowData: rowData,
|
rowData: rowData,
|
||||||
cellDataMap: cellDataMap,
|
cellDataMap: cellDataMap,
|
||||||
);
|
);
|
||||||
|
@ -24,7 +24,7 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
|||||||
_loadCellData();
|
_loadCellData();
|
||||||
},
|
},
|
||||||
didReceiveCellDatas: (_DidReceiveCellDatas value) {
|
didReceiveCellDatas: (_DidReceiveCellDatas value) {
|
||||||
emit(state.copyWith(cellDatas: value.cellDatas));
|
emit(state.copyWith(gridCells: value.gridCells));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -58,16 +58,16 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
|||||||
@freezed
|
@freezed
|
||||||
class RowDetailEvent with _$RowDetailEvent {
|
class RowDetailEvent with _$RowDetailEvent {
|
||||||
const factory RowDetailEvent.initial() = _Initial;
|
const factory RowDetailEvent.initial() = _Initial;
|
||||||
const factory RowDetailEvent.didReceiveCellDatas(List<GridCell> cellDatas) = _DidReceiveCellDatas;
|
const factory RowDetailEvent.didReceiveCellDatas(List<GridCell> gridCells) = _DidReceiveCellDatas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class RowDetailState with _$RowDetailState {
|
class RowDetailState with _$RowDetailState {
|
||||||
const factory RowDetailState({
|
const factory RowDetailState({
|
||||||
required List<GridCell> cellDatas,
|
required List<GridCell> gridCells,
|
||||||
}) = _RowDetailState;
|
}) = _RowDetailState;
|
||||||
|
|
||||||
factory RowDetailState.initial() => RowDetailState(
|
factory RowDetailState.initial() => RowDetailState(
|
||||||
cellDatas: List.empty(),
|
gridCells: List.empty(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ class GridRowCache {
|
|||||||
|
|
||||||
RowUpdateCallback addRowListener({
|
RowUpdateCallback addRowListener({
|
||||||
required String rowId,
|
required String rowId,
|
||||||
void Function(CellDataMap)? onUpdated,
|
void Function(GridCellMap)? onUpdated,
|
||||||
bool Function()? listenWhen,
|
bool Function()? listenWhen,
|
||||||
}) {
|
}) {
|
||||||
listenrHandler() {
|
listenrHandler() {
|
||||||
@ -99,7 +99,7 @@ class GridRowCache {
|
|||||||
notify() {
|
notify() {
|
||||||
final row = _rowNotifier.rowDataWithId(rowId);
|
final row = _rowNotifier.rowDataWithId(rowId);
|
||||||
if (row != null) {
|
if (row != null) {
|
||||||
final CellDataMap cellDataMap = _makeCellDataMap(rowId, row);
|
final GridCellMap cellDataMap = _makeCellDataMap(rowId, row);
|
||||||
onUpdated(cellDataMap);
|
onUpdated(cellDataMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,8 +118,8 @@ class GridRowCache {
|
|||||||
return listenrHandler;
|
return listenrHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
CellDataMap _makeCellDataMap(String rowId, Row? row) {
|
GridCellMap _makeCellDataMap(String rowId, Row? row) {
|
||||||
var cellDataMap = CellDataMap.new();
|
var cellDataMap = GridCellMap.new();
|
||||||
for (final field in _fieldDelegate.fields) {
|
for (final field in _fieldDelegate.fields) {
|
||||||
if (field.visibility) {
|
if (field.visibility) {
|
||||||
cellDataMap[field.id] = GridCell(
|
cellDataMap[field.id] = GridCell(
|
||||||
@ -137,7 +137,7 @@ class GridRowCache {
|
|||||||
_rowNotifier.removeListener(callback);
|
_rowNotifier.removeListener(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
CellDataMap loadCellData(String rowId) {
|
GridCellMap loadCellData(String rowId) {
|
||||||
final Row? data = _rowNotifier.rowDataWithId(rowId);
|
final Row? data = _rowNotifier.rowDataWithId(rowId);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
final payload = RowIdentifierPayload.create()
|
final payload = RowIdentifierPayload.create()
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
|
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType;
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, FieldType;
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'checkbox_cell.dart';
|
import 'checkbox_cell.dart';
|
||||||
import 'date_cell.dart';
|
import 'date_cell.dart';
|
||||||
@ -8,22 +10,47 @@ import 'number_cell.dart';
|
|||||||
import 'selection_cell/selection_cell.dart';
|
import 'selection_cell/selection_cell.dart';
|
||||||
import 'text_cell.dart';
|
import 'text_cell.dart';
|
||||||
|
|
||||||
GridCellWidget buildGridCell(GridCellContext cellContext, {GridCellStyle? style}) {
|
GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCache cellCache, {GridCellStyle? style}) {
|
||||||
final key = ValueKey(cellContext.cellId);
|
final key = ValueKey(gridCell.rowId + gridCell.field.id);
|
||||||
final fieldType = cellContext.cellData.field.fieldType;
|
|
||||||
switch (fieldType) {
|
final cellContext = makeCellContext(gridCell, cellCache);
|
||||||
|
|
||||||
|
switch (gridCell.field.fieldType) {
|
||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
return CheckboxCell(cellContext: cellContext, key: key);
|
return CheckboxCell(cellContext: cellContext, key: key);
|
||||||
case FieldType.DateTime:
|
case FieldType.DateTime:
|
||||||
return DateCell(cellContext: cellContext, key: key);
|
return DateCell(cellContext: cellContext, key: key);
|
||||||
case FieldType.MultiSelect:
|
case FieldType.MultiSelect:
|
||||||
return MultiSelectCell(cellContext: cellContext, style: style, key: key);
|
return MultiSelectCell(cellContext: cellContext as GridCellContext<SelectOptionContext>, style: style, key: key);
|
||||||
case FieldType.Number:
|
case FieldType.Number:
|
||||||
return NumberCell(cellContext: cellContext, key: key);
|
return NumberCell(cellContext: cellContext, key: key);
|
||||||
case FieldType.RichText:
|
case FieldType.RichText:
|
||||||
return GridTextCell(cellContext: cellContext, style: style, key: key);
|
return GridTextCell(cellContext: cellContext, style: style, key: key);
|
||||||
case FieldType.SingleSelect:
|
case FieldType.SingleSelect:
|
||||||
return SingleSelectCell(cellContext: cellContext, style: style, key: key);
|
return SingleSelectCell(cellContext: cellContext as GridCellContext<SelectOptionContext>, style: style, key: key);
|
||||||
|
default:
|
||||||
|
throw UnimplementedError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GridCellContext makeCellContext(GridCell gridCell, GridCellCache cellCache) {
|
||||||
|
switch (gridCell.field.fieldType) {
|
||||||
|
case FieldType.Checkbox:
|
||||||
|
case FieldType.DateTime:
|
||||||
|
case FieldType.Number:
|
||||||
|
case FieldType.RichText:
|
||||||
|
return GridCellContext<Cell>(
|
||||||
|
gridCell: gridCell,
|
||||||
|
cellCache: cellCache,
|
||||||
|
cellDataLoader: DefaultCellDataLoader(gridCell: gridCell),
|
||||||
|
);
|
||||||
|
case FieldType.MultiSelect:
|
||||||
|
case FieldType.SingleSelect:
|
||||||
|
return GridCellContext<SelectOptionContext>(
|
||||||
|
gridCell: gridCell,
|
||||||
|
cellCache: cellCache,
|
||||||
|
cellDataLoader: SelectOptionCellDataLoader(gridCell: gridCell),
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
throw UnimplementedError;
|
throw UnimplementedError;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart';
|
|||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ class SelectOptionCellStyle extends GridCellStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SingleSelectCell extends GridCellWidget {
|
class SingleSelectCell extends GridCellWidget {
|
||||||
final GridCellContext cellContext;
|
final GridCellContext<SelectOptionContext> cellContext;
|
||||||
late final SelectOptionCellStyle? cellStyle;
|
late final SelectOptionCellStyle? cellStyle;
|
||||||
|
|
||||||
SingleSelectCell({
|
SingleSelectCell({
|
||||||
@ -66,9 +67,7 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
|
|||||||
widget.onFocus.value = true;
|
widget.onFocus.value = true;
|
||||||
SelectOptionCellEditor.show(
|
SelectOptionCellEditor.show(
|
||||||
context,
|
context,
|
||||||
state.cellData,
|
widget.cellContext,
|
||||||
state.options,
|
|
||||||
state.selectedOptions,
|
|
||||||
() => widget.onFocus.value = false,
|
() => widget.onFocus.value = false,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -89,7 +88,7 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
|
|||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
class MultiSelectCell extends GridCellWidget {
|
class MultiSelectCell extends GridCellWidget {
|
||||||
final GridCellContext cellContext;
|
final GridCellContext<SelectOptionContext> cellContext;
|
||||||
late final SelectOptionCellStyle? cellStyle;
|
late final SelectOptionCellStyle? cellStyle;
|
||||||
|
|
||||||
MultiSelectCell({
|
MultiSelectCell({
|
||||||
@ -135,9 +134,7 @@ class _MultiSelectCellState extends State<MultiSelectCell> {
|
|||||||
widget.onFocus.value = true;
|
widget.onFocus.value = true;
|
||||||
SelectOptionCellEditor.show(
|
SelectOptionCellEditor.show(
|
||||||
context,
|
context,
|
||||||
state.cellData,
|
widget.cellContext,
|
||||||
state.options,
|
|
||||||
state.selectedOptions,
|
|
||||||
() => widget.onFocus.value = false,
|
() => widget.onFocus.value = false,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -26,15 +26,11 @@ import 'text_field.dart';
|
|||||||
const double _editorPannelWidth = 300;
|
const double _editorPannelWidth = 300;
|
||||||
|
|
||||||
class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||||
final GridCell cellData;
|
final GridCellContext<SelectOptionContext> cellContext;
|
||||||
final List<SelectOption> options;
|
|
||||||
final List<SelectOption> selectedOptions;
|
|
||||||
final VoidCallback onDismissed;
|
final VoidCallback onDismissed;
|
||||||
|
|
||||||
const SelectOptionCellEditor({
|
const SelectOptionCellEditor({
|
||||||
required this.cellData,
|
required this.cellContext,
|
||||||
required this.options,
|
|
||||||
required this.selectedOptions,
|
|
||||||
required this.onDismissed,
|
required this.onDismissed,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -43,9 +39,7 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => SelectOptionEditorBloc(
|
create: (context) => SelectOptionEditorBloc(
|
||||||
cellData: cellData,
|
cellContext: cellContext,
|
||||||
options: options,
|
|
||||||
selectedOptions: selectedOptions,
|
|
||||||
)..add(const SelectOptionEditorEvent.initial()),
|
)..add(const SelectOptionEditorEvent.initial()),
|
||||||
child: BlocBuilder<SelectOptionEditorBloc, SelectOptionEditorState>(
|
child: BlocBuilder<SelectOptionEditorBloc, SelectOptionEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -67,16 +61,12 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
|||||||
|
|
||||||
static void show(
|
static void show(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
GridCell cellData,
|
GridCellContext<SelectOptionContext> cellContext,
|
||||||
List<SelectOption> options,
|
|
||||||
List<SelectOption> selectedOptions,
|
|
||||||
VoidCallback onDismissed,
|
VoidCallback onDismissed,
|
||||||
) {
|
) {
|
||||||
SelectOptionCellEditor.remove(context);
|
SelectOptionCellEditor.remove(context);
|
||||||
final editor = SelectOptionCellEditor(
|
final editor = SelectOptionCellEditor(
|
||||||
cellData: cellData,
|
cellContext: cellContext,
|
||||||
options: options,
|
|
||||||
selectedOptions: selectedOptions,
|
|
||||||
onDismissed: onDismissed,
|
onDismissed: onDismissed,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -170,22 +170,17 @@ class _RowCells extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _makeCells(CellDataMap cellDataMap) {
|
List<Widget> _makeCells(GridCellMap gridCellMap) {
|
||||||
return cellDataMap.values.map(
|
return gridCellMap.values.map(
|
||||||
(cellData) {
|
(gridCell) {
|
||||||
Widget? expander;
|
Widget? expander;
|
||||||
if (cellData.field.isPrimary) {
|
if (gridCell.field.isPrimary) {
|
||||||
expander = _CellExpander(onExpand: onExpand);
|
expander = _CellExpander(onExpand: onExpand);
|
||||||
}
|
}
|
||||||
|
|
||||||
final cellContext = GridCellContext(
|
|
||||||
cellData: cellData,
|
|
||||||
cellCache: cellCache,
|
|
||||||
);
|
|
||||||
|
|
||||||
return CellContainer(
|
return CellContainer(
|
||||||
width: cellData.field.width.toDouble(),
|
width: gridCell.field.width.toDouble(),
|
||||||
child: buildGridCell(cellContext),
|
child: buildGridCellWidget(gridCell, cellCache),
|
||||||
expander: expander,
|
expander: expander,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -84,7 +84,7 @@ class _PropertyList extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RowDetailBloc, RowDetailState>(
|
return BlocBuilder<RowDetailBloc, RowDetailState>(
|
||||||
buildWhen: (previous, current) => previous.cellDatas != current.cellDatas,
|
buildWhen: (previous, current) => previous.gridCells != current.gridCells,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return ScrollbarListStack(
|
return ScrollbarListStack(
|
||||||
axis: Axis.vertical,
|
axis: Axis.vertical,
|
||||||
@ -92,13 +92,12 @@ class _PropertyList extends StatelessWidget {
|
|||||||
barSize: GridSize.scrollBarSize,
|
barSize: GridSize.scrollBarSize,
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemCount: state.cellDatas.length,
|
itemCount: state.gridCells.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
final cellContext = GridCellContext(
|
return _RowDetailCell(
|
||||||
cellData: state.cellDatas[index],
|
gridCell: state.gridCells[index],
|
||||||
cellCache: cellCache,
|
cellCache: cellCache,
|
||||||
);
|
);
|
||||||
return _RowDetailCell(cellContext: cellContext);
|
|
||||||
},
|
},
|
||||||
separatorBuilder: (BuildContext context, int index) {
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
return const VSpace(2);
|
return const VSpace(2);
|
||||||
@ -111,16 +110,22 @@ class _PropertyList extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RowDetailCell extends StatelessWidget {
|
class _RowDetailCell extends StatelessWidget {
|
||||||
final GridCellContext cellContext;
|
final GridCell gridCell;
|
||||||
const _RowDetailCell({required this.cellContext, Key? key}) : super(key: key);
|
final GridCellCache cellCache;
|
||||||
|
const _RowDetailCell({
|
||||||
|
required this.gridCell,
|
||||||
|
required this.cellCache,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
|
|
||||||
final cell = buildGridCell(
|
final cell = buildGridCellWidget(
|
||||||
cellContext,
|
gridCell,
|
||||||
style: _buildCellStyle(theme, cellContext.fieldType),
|
cellCache,
|
||||||
|
style: _buildCellStyle(theme, gridCell.field.fieldType),
|
||||||
);
|
);
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 36,
|
height: 36,
|
||||||
@ -130,7 +135,7 @@ class _RowDetailCell extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 150,
|
width: 150,
|
||||||
child: FieldCellButton(field: cellContext.field, onTap: () => _showFieldEditor(context)),
|
child: FieldCellButton(field: gridCell.field, onTap: () => _showFieldEditor(context)),
|
||||||
),
|
),
|
||||||
const HSpace(10),
|
const HSpace(10),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -146,10 +151,10 @@ class _RowDetailCell extends StatelessWidget {
|
|||||||
|
|
||||||
void _showFieldEditor(BuildContext context) {
|
void _showFieldEditor(BuildContext context) {
|
||||||
FieldEditor(
|
FieldEditor(
|
||||||
gridId: cellContext.gridId,
|
gridId: gridCell.gridId,
|
||||||
fieldContextLoader: FieldContextLoaderAdaptor(
|
fieldContextLoader: FieldContextLoaderAdaptor(
|
||||||
gridId: cellContext.gridId,
|
gridId: gridCell.gridId,
|
||||||
field: cellContext.field,
|
field: gridCell.field,
|
||||||
),
|
),
|
||||||
).show(context);
|
).show(context);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user