chore: build board card ui

This commit is contained in:
appflowy 2022-08-12 16:06:30 +08:00
parent 5de6a7447a
commit 055868bae3
34 changed files with 447 additions and 189 deletions

View File

@ -44,7 +44,7 @@
"type": "dart", "type": "dart",
"preLaunchTask": "AF: Clean + Rebuild All", "preLaunchTask": "AF: Clean + Rebuild All",
"env": { "env": {
"RUST_LOG": "info" "RUST_LOG": "trace"
}, },
"cwd": "${workspaceRoot}/app_flowy" "cwd": "${workspaceRoot}/app_flowy"
}, },

View File

@ -41,8 +41,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
) {}, ) {},
); );
// boardDataController.addColumns(_buildColumns());
on<BoardEvent>( on<BoardEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
@ -87,6 +85,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
return AFBoardColumnData( return AFBoardColumnData(
id: group.groupId, id: group.groupId,
desc: group.desc, desc: group.desc,
items: _buildRows(group.rows),
customData: group, customData: group,
); );
}).toList(); }).toList();
@ -99,6 +98,20 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
); );
} }
List<BoardColumnItem> _buildRows(List<RowPB> rows) {
return rows.map((row) {
final rowInfo = RowInfo(
gridId: _dataController.gridId,
blockId: row.blockId,
id: row.id,
fields: _dataController.fieldCache.unmodifiableFields,
height: row.height.toDouble(),
rawRow: row,
);
return BoardColumnItem(row: rowInfo);
}).toList();
}
Future<void> _loadGrid(Emitter<BoardState> emit) async { Future<void> _loadGrid(Emitter<BoardState> emit) async {
final result = await _dataController.loadData(); final result = await _dataController.loadData();
result.fold( result.fold(
@ -172,21 +185,11 @@ class GridFieldEquatable extends Equatable {
UnmodifiableListView<FieldPB> get value => UnmodifiableListView(_fields); UnmodifiableListView<FieldPB> get value => UnmodifiableListView(_fields);
} }
class TextItem extends ColumnItem { class BoardColumnItem extends AFColumnItem {
final String s; final RowInfo row;
TextItem(this.s); BoardColumnItem({required this.row});
@override @override
String get id => s; String get id => row.id;
}
class RichTextItem extends ColumnItem {
final String title;
final String subtitle;
RichTextItem({required this.title, required this.subtitle});
@override
String get id => title;
} }

View File

@ -0,0 +1,76 @@
import 'dart:async';
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
part 'board_select_option_cell_bloc.freezed.dart';
class BoardSelectOptionCellBloc
extends Bloc<BoardSelectOptionCellEvent, BoardSelectOptionCellState> {
final GridSelectOptionCellController cellController;
void Function()? _onCellChangedFn;
BoardSelectOptionCellBloc({
required this.cellController,
}) : super(BoardSelectOptionCellState.initial(cellController)) {
on<BoardSelectOptionCellEvent>(
(event, emit) async {
await event.when(
initial: () async {
_startListening();
},
didReceiveOptions: (List<SelectOptionPB> selectedOptions) {
emit(state.copyWith(selectedOptions: selectedOptions));
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.startListening(
onCellChanged: ((selectOptionContext) {
if (!isClosed) {
add(BoardSelectOptionCellEvent.didReceiveOptions(
selectOptionContext?.selectOptions ?? [],
));
}
}),
);
}
}
@freezed
class BoardSelectOptionCellEvent with _$BoardSelectOptionCellEvent {
const factory BoardSelectOptionCellEvent.initial() = _InitialCell;
const factory BoardSelectOptionCellEvent.didReceiveOptions(
List<SelectOptionPB> selectedOptions,
) = _DidReceiveOptions;
}
@freezed
class BoardSelectOptionCellState with _$BoardSelectOptionCellState {
const factory BoardSelectOptionCellState({
required List<SelectOptionPB> selectedOptions,
}) = _BoardSelectOptionCellState;
factory BoardSelectOptionCellState.initial(
GridSelectOptionCellController context) {
final data = context.getCellData();
return BoardSelectOptionCellState(
selectedOptions: data?.selectOptions ?? [],
);
}
}

View File

@ -0,0 +1,66 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
part 'board_text_cell_bloc.freezed.dart';
class BoardTextCellBloc extends Bloc<BoardTextCellEvent, BoardTextCellState> {
final GridCellController cellController;
void Function()? _onCellChangedFn;
BoardTextCellBloc({
required this.cellController,
}) : super(BoardTextCellState.initial(cellController)) {
on<BoardTextCellEvent>(
(event, emit) async {
await event.when(
initial: () async {
_startListening();
},
didReceiveCellUpdate: (content) {
emit(state.copyWith(content: content));
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.startListening(
onCellChanged: ((cellContent) {
if (!isClosed) {
add(BoardTextCellEvent.didReceiveCellUpdate(cellContent ?? ""));
}
}),
);
}
}
@freezed
class BoardTextCellEvent with _$BoardTextCellEvent {
const factory BoardTextCellEvent.initial() = _InitialCell;
const factory BoardTextCellEvent.didReceiveCellUpdate(String cellContent) =
_DidReceiveCellUpdate;
}
@freezed
class BoardTextCellState with _$BoardTextCellState {
const factory BoardTextCellState({
required String content,
}) = _BoardTextCellState;
factory BoardTextCellState.initial(GridCellController context) =>
BoardTextCellState(
content: context.getCellData() ?? "",
);
}

View File

@ -1,13 +1,12 @@
// ignore_for_file: unused_field // ignore_for_file: unused_field
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:appflowy_board/appflowy_board.dart'; import 'package:appflowy_board/appflowy_board.dart';
import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.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';
import '../application/board_bloc.dart'; import '../application/board_bloc.dart';
import 'card.dart'; import 'card/card.dart';
class BoardPage extends StatelessWidget { class BoardPage extends StatelessWidget {
final ViewPB view; final ViewPB view;
@ -87,8 +86,8 @@ class BoardContent extends StatelessWidget {
); );
} }
Widget _buildCard(BuildContext context, ColumnItem item) { Widget _buildCard(BuildContext context, AFColumnItem item) {
final rowInfo = item as RowInfo; final rowInfo = (item as BoardColumnItem).row;
return AppFlowyColumnItemCard( return AppFlowyColumnItemCard(
key: ObjectKey(item), key: ObjectKey(item),
child: BoardCard(rowInfo: rowInfo), child: BoardCard(rowInfo: rowInfo),

View File

@ -0,0 +1,51 @@
import 'package:app_flowy/plugins/board/application/card/board_select_option_cell_bloc.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BoardSelectOptionCell extends StatefulWidget {
final GridCellControllerBuilder cellControllerBuilder;
const BoardSelectOptionCell({
required this.cellControllerBuilder,
Key? key,
}) : super(key: key);
@override
State<BoardSelectOptionCell> createState() => _BoardSelectOptionCellState();
}
class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
late BoardSelectOptionCellBloc _cellBloc;
@override
void initState() {
final cellController =
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
_cellBloc = BoardSelectOptionCellBloc(cellController: cellController)
..add(const BoardSelectOptionCellEvent.initial());
super.initState();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: _cellBloc,
child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
builder: (context, state) {
return SelectOptionWrap(
selectOptions: state.selectedOptions,
cellControllerBuilder: widget.cellControllerBuilder,
);
},
),
);
}
@override
Future<void> dispose() async {
_cellBloc.close();
super.dispose();
}
}

View File

@ -0,0 +1,49 @@
import 'package:app_flowy/plugins/board/application/card/board_text_cell_bloc.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BoardTextCell extends StatefulWidget {
final GridCellControllerBuilder cellControllerBuilder;
const BoardTextCell({required this.cellControllerBuilder, Key? key})
: super(key: key);
@override
State<BoardTextCell> createState() => _BoardTextCellState();
}
class _BoardTextCellState extends State<BoardTextCell> {
late BoardTextCellBloc _cellBloc;
@override
void initState() {
final cellController =
widget.cellControllerBuilder.build() as GridCellController;
_cellBloc = BoardTextCellBloc(cellController: cellController)
..add(const BoardTextCellEvent.initial());
super.initState();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: _cellBloc,
child: BlocBuilder<BoardTextCellBloc, BoardTextCellState>(
builder: (context, state) {
return SizedBox(
height: 30,
child: FlowyText.medium(state.content),
);
},
),
);
}
@override
Future<void> dispose() async {
_cellBloc.close();
super.dispose();
}
}

View File

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

View File

@ -6,13 +6,13 @@ import 'cell_service/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 GridCellController cellContext; final GridCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
CheckboxCellBloc({ CheckboxCellBloc({
required CellService service, required CellService service,
required this.cellContext, required this.cellController,
}) : super(CheckboxCellState.initial(cellContext)) { }) : super(CheckboxCellState.initial(cellController)) {
on<CheckboxCellEvent>( on<CheckboxCellEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
@ -33,16 +33,17 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening(onCellChanged: ((cellData) { _onCellChangedFn =
cellController.startListening(onCellChanged: ((cellData) {
if (!isClosed) { if (!isClosed) {
add(CheckboxCellEvent.didReceiveCellUpdate(cellData)); add(CheckboxCellEvent.didReceiveCellUpdate(cellData));
} }
@ -50,7 +51,7 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
} }
void _updateCellData() { void _updateCellData() {
cellContext.saveCellData(!state.isSelected ? "Yes" : "No"); cellController.saveCellData(!state.isSelected ? "Yes" : "No");
} }
} }
@ -58,7 +59,8 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
class CheckboxCellEvent with _$CheckboxCellEvent { class CheckboxCellEvent with _$CheckboxCellEvent {
const factory CheckboxCellEvent.initial() = _Initial; const factory CheckboxCellEvent.initial() = _Initial;
const factory CheckboxCellEvent.select() = _Selected; const factory CheckboxCellEvent.select() = _Selected;
const factory CheckboxCellEvent.didReceiveCellUpdate(String? cellData) = _DidReceiveCellUpdate; const factory CheckboxCellEvent.didReceiveCellUpdate(String? cellData) =
_DidReceiveCellUpdate;
} }
@freezed @freezed

View File

@ -18,14 +18,14 @@ import 'package:fixnum/fixnum.dart' as $fixnum;
part 'date_cal_bloc.freezed.dart'; part 'date_cal_bloc.freezed.dart';
class DateCalBloc extends Bloc<DateCalEvent, DateCalState> { class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
final GridDateCellController cellContext; final GridDateCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
DateCalBloc({ DateCalBloc({
required DateTypeOption dateTypeOption, required DateTypeOptionPB dateTypeOptionPB,
required DateCellDataPB? cellData, required DateCellDataPB? cellData,
required this.cellContext, required this.cellController,
}) : super(DateCalState.initial(dateTypeOption, cellData)) { }) : super(DateCalState.initial(dateTypeOptionPB, cellData)) {
on<DateCalEvent>( on<DateCalEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
@ -102,7 +102,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
} }
} }
cellContext.saveCellData(newCalData, resultCallback: (result) { cellController.saveCellData(newCalData, resultCallback: (result) {
result.fold( result.fold(
() => updateCalData(Some(newCalData), none()), () => updateCalData(Some(newCalData), none()),
(err) { (err) {
@ -120,7 +120,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
String timeFormatPrompt(FlowyError error) { String timeFormatPrompt(FlowyError error) {
String msg = LocaleKeys.grid_field_invalidTimeFormat.tr() + ". "; String msg = LocaleKeys.grid_field_invalidTimeFormat.tr() + ". ";
switch (state.dateTypeOption.timeFormat) { switch (state.dateTypeOptionPB.timeFormat) {
case TimeFormat.TwelveHour: case TimeFormat.TwelveHour:
msg = msg + "e.g. 01: 00 AM"; msg = msg + "e.g. 01: 00 AM";
break; break;
@ -136,15 +136,15 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((cell) { onCellChanged: ((cell) {
if (!isClosed) { if (!isClosed) {
add(DateCalEvent.didReceiveCellUpdate(cell)); add(DateCalEvent.didReceiveCellUpdate(cell));
@ -159,8 +159,8 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
TimeFormat? timeFormat, TimeFormat? timeFormat,
bool? includeTime, bool? includeTime,
}) async { }) async {
state.dateTypeOption.freeze(); state.dateTypeOptionPB.freeze();
final newDateTypeOption = state.dateTypeOption.rebuild((typeOption) { final newDateTypeOption = state.dateTypeOptionPB.rebuild((typeOption) {
if (dateFormat != null) { if (dateFormat != null) {
typeOption.dateFormat = dateFormat; typeOption.dateFormat = dateFormat;
} }
@ -175,14 +175,14 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
}); });
final result = await FieldService.updateFieldTypeOption( final result = await FieldService.updateFieldTypeOption(
gridId: cellContext.gridId, gridId: cellController.gridId,
fieldId: cellContext.field.id, fieldId: cellController.field.id,
typeOptionData: newDateTypeOption.writeToBuffer(), typeOptionData: newDateTypeOption.writeToBuffer(),
); );
result.fold( result.fold(
(l) => emit(state.copyWith( (l) => emit(state.copyWith(
dateTypeOption: newDateTypeOption, dateTypeOptionPB: newDateTypeOption,
timeHintText: _timeHintText(newDateTypeOption))), timeHintText: _timeHintText(newDateTypeOption))),
(err) => Log.error(err), (err) => Log.error(err),
); );
@ -210,7 +210,7 @@ class DateCalEvent with _$DateCalEvent {
@freezed @freezed
class DateCalState with _$DateCalState { class DateCalState with _$DateCalState {
const factory DateCalState({ const factory DateCalState({
required DateTypeOption dateTypeOption, required DateTypeOptionPB dateTypeOptionPB,
required CalendarFormat format, required CalendarFormat format,
required DateTime focusedDay, required DateTime focusedDay,
required Option<String> timeFormatError, required Option<String> timeFormatError,
@ -220,24 +220,24 @@ class DateCalState with _$DateCalState {
}) = _DateCalState; }) = _DateCalState;
factory DateCalState.initial( factory DateCalState.initial(
DateTypeOption dateTypeOption, DateTypeOptionPB dateTypeOptionPB,
DateCellDataPB? cellData, DateCellDataPB? cellData,
) { ) {
Option<CalendarData> calData = calDataFromCellData(cellData); Option<CalendarData> calData = calDataFromCellData(cellData);
final time = calData.foldRight("", (dateData, previous) => dateData.time); final time = calData.foldRight("", (dateData, previous) => dateData.time);
return DateCalState( return DateCalState(
dateTypeOption: dateTypeOption, dateTypeOptionPB: dateTypeOptionPB,
format: CalendarFormat.month, format: CalendarFormat.month,
focusedDay: DateTime.now(), focusedDay: DateTime.now(),
time: time, time: time,
calData: calData, calData: calData,
timeFormatError: none(), timeFormatError: none(),
timeHintText: _timeHintText(dateTypeOption), timeHintText: _timeHintText(dateTypeOptionPB),
); );
} }
} }
String _timeHintText(DateTypeOption typeOption) { String _timeHintText(DateTypeOptionPB typeOption) {
switch (typeOption.timeFormat) { switch (typeOption.timeFormat) {
case TimeFormat.TwelveHour: case TimeFormat.TwelveHour:
return LocaleKeys.document_date_timeHintTextInTwelveHour.tr(); return LocaleKeys.document_date_timeHintTextInTwelveHour.tr();

View File

@ -7,11 +7,11 @@ import 'cell_service/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 GridDateCellController cellContext; final GridDateCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
DateCellBloc({required this.cellContext}) DateCellBloc({required this.cellController})
: super(DateCellState.initial(cellContext)) { : super(DateCellState.initial(cellController)) {
on<DateCellEvent>( on<DateCellEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
@ -30,15 +30,15 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((data) { onCellChanged: ((data) {
if (!isClosed) { if (!isClosed) {
add(DateCellEvent.didReceiveCellUpdate(data)); add(DateCellEvent.didReceiveCellUpdate(data));

View File

@ -8,12 +8,12 @@ import 'cell_service/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 GridCellController cellContext; final GridCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
NumberCellBloc({ NumberCellBloc({
required this.cellContext, required this.cellController,
}) : super(NumberCellState.initial(cellContext)) { }) : super(NumberCellState.initial(cellController)) {
on<NumberCellEvent>( on<NumberCellEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
@ -24,11 +24,13 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
emit(state.copyWith(content: content)); emit(state.copyWith(content: content));
}, },
updateCell: (text) { updateCell: (text) {
cellContext.saveCellData(text, resultCallback: (result) { cellController.saveCellData(text, resultCallback: (result) {
result.fold( result.fold(
() => null, () => null,
(err) { (err) {
if (!isClosed) add(NumberCellEvent.didReceiveCellUpdate(right(err))); if (!isClosed) {
add(NumberCellEvent.didReceiveCellUpdate(right(err)));
}
}, },
); );
}); });
@ -41,15 +43,15 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((cellContent) { onCellChanged: ((cellContent) {
if (!isClosed) { if (!isClosed) {
add(NumberCellEvent.didReceiveCellUpdate(left(cellContent ?? ""))); add(NumberCellEvent.didReceiveCellUpdate(left(cellContent ?? "")));
@ -63,7 +65,8 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
class NumberCellEvent with _$NumberCellEvent { class NumberCellEvent with _$NumberCellEvent {
const factory NumberCellEvent.initial() = _Initial; const factory NumberCellEvent.initial() = _Initial;
const factory NumberCellEvent.updateCell(String text) = _UpdateCell; const factory NumberCellEvent.updateCell(String text) = _UpdateCell;
const factory NumberCellEvent.didReceiveCellUpdate(Either<String, FlowyError> cellContent) = _DidReceiveCellUpdate; const factory NumberCellEvent.didReceiveCellUpdate(
Either<String, FlowyError> cellContent) = _DidReceiveCellUpdate;
} }
@freezed @freezed

View File

@ -8,12 +8,12 @@ part 'select_option_cell_bloc.freezed.dart';
class SelectOptionCellBloc class SelectOptionCellBloc
extends Bloc<SelectOptionCellEvent, SelectOptionCellState> { extends Bloc<SelectOptionCellEvent, SelectOptionCellState> {
final GridSelectOptionCellController cellContext; final GridSelectOptionCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
SelectOptionCellBloc({ SelectOptionCellBloc({
required this.cellContext, required this.cellController,
}) : super(SelectOptionCellState.initial(cellContext)) { }) : super(SelectOptionCellState.initial(cellController)) {
on<SelectOptionCellEvent>( on<SelectOptionCellEvent>(
(event, emit) async { (event, emit) async {
await event.map( await event.map(
@ -33,15 +33,15 @@ class SelectOptionCellBloc
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((selectOptionContext) { onCellChanged: ((selectOptionContext) {
if (!isClosed) { if (!isClosed) {
add(SelectOptionCellEvent.didReceiveOptions( add(SelectOptionCellEvent.didReceiveOptions(

View File

@ -6,11 +6,11 @@ import 'cell_service/cell_service.dart';
part 'text_cell_bloc.freezed.dart'; part 'text_cell_bloc.freezed.dart';
class TextCellBloc extends Bloc<TextCellEvent, TextCellState> { class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
final GridCellController cellContext; final GridCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
TextCellBloc({ TextCellBloc({
required this.cellContext, required this.cellController,
}) : super(TextCellState.initial(cellContext)) { }) : super(TextCellState.initial(cellController)) {
on<TextCellEvent>( on<TextCellEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
@ -18,7 +18,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
_startListening(); _startListening();
}, },
updateText: (text) { updateText: (text) {
cellContext.saveCellData(text); cellController.saveCellData(text);
emit(state.copyWith(content: text)); emit(state.copyWith(content: text));
}, },
didReceiveCellUpdate: (content) { didReceiveCellUpdate: (content) {
@ -32,15 +32,15 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((cellContent) { onCellChanged: ((cellContent) {
if (!isClosed) { if (!isClosed) {
add(TextCellEvent.didReceiveCellUpdate(cellContent ?? "")); add(TextCellEvent.didReceiveCellUpdate(cellContent ?? ""));
@ -53,7 +53,8 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
@freezed @freezed
class TextCellEvent with _$TextCellEvent { class TextCellEvent with _$TextCellEvent {
const factory TextCellEvent.initial() = _InitialCell; const factory TextCellEvent.initial() = _InitialCell;
const factory TextCellEvent.didReceiveCellUpdate(String cellContent) = _DidReceiveCellUpdate; const factory TextCellEvent.didReceiveCellUpdate(String cellContent) =
_DidReceiveCellUpdate;
const factory TextCellEvent.updateText(String text) = _UpdateText; const factory TextCellEvent.updateText(String text) = _UpdateText;
} }

View File

@ -7,11 +7,11 @@ import 'cell_service/cell_service.dart';
part 'url_cell_bloc.freezed.dart'; part 'url_cell_bloc.freezed.dart';
class URLCellBloc extends Bloc<URLCellEvent, URLCellState> { class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
final GridURLCellController cellContext; final GridURLCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
URLCellBloc({ URLCellBloc({
required this.cellContext, required this.cellController,
}) : super(URLCellState.initial(cellContext)) { }) : super(URLCellState.initial(cellController)) {
on<URLCellEvent>( on<URLCellEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
@ -25,7 +25,7 @@ class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
)); ));
}, },
updateURL: (String url) { updateURL: (String url) {
cellContext.saveCellData(url, deduplicate: true); cellController.saveCellData(url, deduplicate: true);
}, },
); );
}, },
@ -35,15 +35,15 @@ class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((cellData) { onCellChanged: ((cellData) {
if (!isClosed) { if (!isClosed) {
add(URLCellEvent.didReceiveCellUpdate(cellData)); add(URLCellEvent.didReceiveCellUpdate(cellData));
@ -57,7 +57,8 @@ class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
class URLCellEvent with _$URLCellEvent { class URLCellEvent with _$URLCellEvent {
const factory URLCellEvent.initial() = _InitialCell; const factory URLCellEvent.initial() = _InitialCell;
const factory URLCellEvent.updateURL(String url) = _UpdateURL; const factory URLCellEvent.updateURL(String url) = _UpdateURL;
const factory URLCellEvent.didReceiveCellUpdate(URLCellDataPB? cell) = _DidReceiveCellUpdate; const factory URLCellEvent.didReceiveCellUpdate(URLCellDataPB? cell) =
_DidReceiveCellUpdate;
} }
@freezed @freezed

View File

@ -7,11 +7,11 @@ import 'cell_service/cell_service.dart';
part 'url_cell_editor_bloc.freezed.dart'; part 'url_cell_editor_bloc.freezed.dart';
class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> { class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
final GridURLCellController cellContext; final GridURLCellController cellController;
void Function()? _onCellChangedFn; void Function()? _onCellChangedFn;
URLCellEditorBloc({ URLCellEditorBloc({
required this.cellContext, required this.cellController,
}) : super(URLCellEditorState.initial(cellContext)) { }) : super(URLCellEditorState.initial(cellController)) {
on<URLCellEditorEvent>( on<URLCellEditorEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
@ -19,7 +19,7 @@ class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
_startListening(); _startListening();
}, },
updateText: (text) { updateText: (text) {
cellContext.saveCellData(text, deduplicate: true); cellController.saveCellData(text, deduplicate: true);
emit(state.copyWith(content: text)); emit(state.copyWith(content: text));
}, },
didReceiveCellUpdate: (cellData) { didReceiveCellUpdate: (cellData) {
@ -33,15 +33,15 @@ class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
@override @override
Future<void> close() async { Future<void> close() async {
if (_onCellChangedFn != null) { if (_onCellChangedFn != null) {
cellContext.removeListener(_onCellChangedFn!); cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null; _onCellChangedFn = null;
} }
cellContext.dispose(); cellController.dispose();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_onCellChangedFn = cellContext.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((cellData) { onCellChanged: ((cellData) {
if (!isClosed) { if (!isClosed) {
add(URLCellEditorEvent.didReceiveCellUpdate(cellData)); add(URLCellEditorEvent.didReceiveCellUpdate(cellData));
@ -54,7 +54,8 @@ class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
@freezed @freezed
class URLCellEditorEvent with _$URLCellEditorEvent { class URLCellEditorEvent with _$URLCellEditorEvent {
const factory URLCellEditorEvent.initial() = _InitialCell; const factory URLCellEditorEvent.initial() = _InitialCell;
const factory URLCellEditorEvent.didReceiveCellUpdate(URLCellDataPB? cell) = _DidReceiveCellUpdate; const factory URLCellEditorEvent.didReceiveCellUpdate(URLCellDataPB? cell) =
_DidReceiveCellUpdate;
const factory URLCellEditorEvent.updateText(String text) = _UpdateText; const factory URLCellEditorEvent.updateText(String text) = _UpdateText;
} }

View File

@ -32,7 +32,7 @@ class DateTypeOptionBloc
); );
} }
DateTypeOption _updateTypeOption({ DateTypeOptionPB _updateTypeOption({
DateFormat? dateFormat, DateFormat? dateFormat,
TimeFormat? timeFormat, TimeFormat? timeFormat,
bool? includeTime, bool? includeTime,
@ -72,9 +72,9 @@ class DateTypeOptionEvent with _$DateTypeOptionEvent {
@freezed @freezed
class DateTypeOptionState with _$DateTypeOptionState { class DateTypeOptionState with _$DateTypeOptionState {
const factory DateTypeOptionState({ const factory DateTypeOptionState({
required DateTypeOption typeOption, required DateTypeOptionPB typeOption,
}) = _DateTypeOptionState; }) = _DateTypeOptionState;
factory DateTypeOptionState.initial(DateTypeOption typeOption) => factory DateTypeOptionState.initial(DateTypeOptionPB typeOption) =>
DateTypeOptionState(typeOption: typeOption); DateTypeOptionState(typeOption: typeOption);
} }

View File

@ -23,7 +23,7 @@ class NumberTypeOptionBloc
); );
} }
NumberTypeOption _updateNumberFormat(NumberFormat format) { NumberTypeOptionPB _updateNumberFormat(NumberFormat format) {
state.typeOption.freeze(); state.typeOption.freeze();
return state.typeOption.rebuild((typeOption) { return state.typeOption.rebuild((typeOption) {
typeOption.format = format; typeOption.format = format;
@ -45,10 +45,10 @@ class NumberTypeOptionEvent with _$NumberTypeOptionEvent {
@freezed @freezed
class NumberTypeOptionState with _$NumberTypeOptionState { class NumberTypeOptionState with _$NumberTypeOptionState {
const factory NumberTypeOptionState({ const factory NumberTypeOptionState({
required NumberTypeOption typeOption, required NumberTypeOptionPB typeOption,
}) = _NumberTypeOptionState; }) = _NumberTypeOptionState;
factory NumberTypeOptionState.initial(NumberTypeOption typeOption) => factory NumberTypeOptionState.initial(NumberTypeOptionPB typeOption) =>
NumberTypeOptionState( NumberTypeOptionState(
typeOption: typeOption, typeOption: typeOption,
); );

View File

@ -18,56 +18,56 @@ abstract class TypeOptionDataParser<T> {
} }
// Number // Number
typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOption>; typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOptionPB>;
class NumberTypeOptionWidgetDataParser class NumberTypeOptionWidgetDataParser
extends TypeOptionDataParser<NumberTypeOption> { extends TypeOptionDataParser<NumberTypeOptionPB> {
@override @override
NumberTypeOption fromBuffer(List<int> buffer) { NumberTypeOptionPB fromBuffer(List<int> buffer) {
return NumberTypeOption.fromBuffer(buffer); return NumberTypeOptionPB.fromBuffer(buffer);
} }
} }
// RichText // RichText
typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOption>; typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOptionPB>;
class RichTextTypeOptionWidgetDataParser class RichTextTypeOptionWidgetDataParser
extends TypeOptionDataParser<RichTextTypeOption> { extends TypeOptionDataParser<RichTextTypeOptionPB> {
@override @override
RichTextTypeOption fromBuffer(List<int> buffer) { RichTextTypeOptionPB fromBuffer(List<int> buffer) {
return RichTextTypeOption.fromBuffer(buffer); return RichTextTypeOptionPB.fromBuffer(buffer);
} }
} }
// Checkbox // Checkbox
typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOption>; typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOptionPB>;
class CheckboxTypeOptionWidgetDataParser class CheckboxTypeOptionWidgetDataParser
extends TypeOptionDataParser<CheckboxTypeOption> { extends TypeOptionDataParser<CheckboxTypeOptionPB> {
@override @override
CheckboxTypeOption fromBuffer(List<int> buffer) { CheckboxTypeOptionPB fromBuffer(List<int> buffer) {
return CheckboxTypeOption.fromBuffer(buffer); return CheckboxTypeOptionPB.fromBuffer(buffer);
} }
} }
// URL // URL
typedef URLTypeOptionContext = TypeOptionContext<URLTypeOption>; typedef URLTypeOptionContext = TypeOptionContext<URLTypeOptionPB>;
class URLTypeOptionWidgetDataParser class URLTypeOptionWidgetDataParser
extends TypeOptionDataParser<URLTypeOption> { extends TypeOptionDataParser<URLTypeOptionPB> {
@override @override
URLTypeOption fromBuffer(List<int> buffer) { URLTypeOptionPB fromBuffer(List<int> buffer) {
return URLTypeOption.fromBuffer(buffer); return URLTypeOptionPB.fromBuffer(buffer);
} }
} }
// Date // Date
typedef DateTypeOptionContext = TypeOptionContext<DateTypeOption>; typedef DateTypeOptionContext = TypeOptionContext<DateTypeOptionPB>;
class DateTypeOptionDataParser extends TypeOptionDataParser<DateTypeOption> { class DateTypeOptionDataParser extends TypeOptionDataParser<DateTypeOptionPB> {
@override @override
DateTypeOption fromBuffer(List<int> buffer) { DateTypeOptionPB fromBuffer(List<int> buffer) {
return DateTypeOption.fromBuffer(buffer); return DateTypeOptionPB.fromBuffer(buffer);
} }
} }

View File

@ -84,7 +84,7 @@ class _DateCellState extends GridCellState<GridDateCell> {
DateCellEditor(onDismissed: () => widget.onCellEditing.value = false); DateCellEditor(onDismissed: () => widget.onCellEditing.value = false);
calendar.show( calendar.show(
context, context,
cellController: bloc.cellContext.clone(), cellController: bloc.cellController.clone(),
); );
} }

View File

@ -40,10 +40,10 @@ class DateCellEditor with FlowyOverlayDelegate {
final result = final result =
await cellController.getFieldTypeOption(DateTypeOptionDataParser()); await cellController.getFieldTypeOption(DateTypeOptionDataParser());
result.fold( result.fold(
(dateTypeOption) { (dateTypeOptionPB) {
final calendar = _CellCalendarWidget( final calendar = _CellCalendarWidget(
cellContext: cellController, cellContext: cellController,
dateTypeOption: dateTypeOption, dateTypeOptionPB: dateTypeOptionPB,
); );
FlowyOverlay.of(context).insertWithAnchor( FlowyOverlay.of(context).insertWithAnchor(
@ -79,11 +79,11 @@ class DateCellEditor with FlowyOverlayDelegate {
class _CellCalendarWidget extends StatelessWidget { class _CellCalendarWidget extends StatelessWidget {
final GridDateCellController cellContext; final GridDateCellController cellContext;
final DateTypeOption dateTypeOption; final DateTypeOptionPB dateTypeOptionPB;
const _CellCalendarWidget({ const _CellCalendarWidget({
required this.cellContext, required this.cellContext,
required this.dateTypeOption, required this.dateTypeOptionPB,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -93,9 +93,9 @@ class _CellCalendarWidget extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) { create: (context) {
return DateCalBloc( return DateCalBloc(
dateTypeOption: dateTypeOption, dateTypeOptionPB: dateTypeOptionPB,
cellData: cellContext.getCellData(), cellData: cellContext.getCellData(),
cellContext: cellContext, cellController: cellContext,
)..add(const DateCalEvent.initial()); )..add(const DateCalEvent.initial());
}, },
child: BlocBuilder<DateCalBloc, DateCalState>( child: BlocBuilder<DateCalBloc, DateCalState>(
@ -197,7 +197,7 @@ class _IncludeTimeButton extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return BlocSelector<DateCalBloc, DateCalState, bool>( return BlocSelector<DateCalBloc, DateCalState, bool>(
selector: (state) => state.dateTypeOption.includeTime, selector: (state) => state.dateTypeOptionPB.includeTime,
builder: (context, includeTime) { builder: (context, includeTime) {
return SizedBox( return SizedBox(
height: 50, height: 50,
@ -244,7 +244,7 @@ class _TimeTextFieldState extends State<_TimeTextField> {
void initState() { void initState() {
_focusNode = FocusNode(); _focusNode = FocusNode();
_controller = TextEditingController(text: widget.bloc.state.time); _controller = TextEditingController(text: widget.bloc.state.time);
if (widget.bloc.state.dateTypeOption.includeTime) { if (widget.bloc.state.dateTypeOptionPB.includeTime) {
_focusNode.addListener(() { _focusNode.addListener(() {
if (mounted) { if (mounted) {
_CalDateTimeSetting.hide(context); _CalDateTimeSetting.hide(context);
@ -265,7 +265,7 @@ class _TimeTextFieldState extends State<_TimeTextField> {
}, },
listenWhen: (p, c) => p.time != c.time, listenWhen: (p, c) => p.time != c.time,
builder: (context, state) { builder: (context, state) {
if (state.dateTypeOption.includeTime) { if (state.dateTypeOptionPB.includeTime) {
return Padding( return Padding(
padding: kMargin, padding: kMargin,
child: RoundedInputField( child: RoundedInputField(
@ -307,23 +307,24 @@ class _DateTypeOptionButton extends StatelessWidget {
final title = LocaleKeys.grid_field_dateFormat.tr() + final title = LocaleKeys.grid_field_dateFormat.tr() +
" &" + " &" +
LocaleKeys.grid_field_timeFormat.tr(); LocaleKeys.grid_field_timeFormat.tr();
return BlocSelector<DateCalBloc, DateCalState, DateTypeOption>( return BlocSelector<DateCalBloc, DateCalState, DateTypeOptionPB>(
selector: (state) => state.dateTypeOption, selector: (state) => state.dateTypeOptionPB,
builder: (context, dateTypeOption) { builder: (context, dateTypeOptionPB) {
return FlowyButton( return FlowyButton(
text: FlowyText.medium(title, fontSize: 12), text: FlowyText.medium(title, fontSize: 12),
hoverColor: theme.hover, hoverColor: theme.hover,
margin: kMargin, margin: kMargin,
onTap: () => _showTimeSetting(dateTypeOption, context), onTap: () => _showTimeSetting(dateTypeOptionPB, context),
rightIcon: svgWidget("grid/more", color: theme.iconColor), rightIcon: svgWidget("grid/more", color: theme.iconColor),
); );
}, },
); );
} }
void _showTimeSetting(DateTypeOption dateTypeOption, BuildContext context) { void _showTimeSetting(
DateTypeOptionPB dateTypeOptionPB, BuildContext context) {
final setting = _CalDateTimeSetting( final setting = _CalDateTimeSetting(
dateTypeOption: dateTypeOption, dateTypeOptionPB: dateTypeOptionPB,
onEvent: (event) => context.read<DateCalBloc>().add(event), onEvent: (event) => context.read<DateCalBloc>().add(event),
); );
setting.show(context); setting.show(context);
@ -331,10 +332,10 @@ class _DateTypeOptionButton extends StatelessWidget {
} }
class _CalDateTimeSetting extends StatefulWidget { class _CalDateTimeSetting extends StatefulWidget {
final DateTypeOption dateTypeOption; final DateTypeOptionPB dateTypeOptionPB;
final Function(DateCalEvent) onEvent; final Function(DateCalEvent) onEvent;
const _CalDateTimeSetting( const _CalDateTimeSetting(
{required this.dateTypeOption, required this.onEvent, Key? key}) {required this.dateTypeOptionPB, required this.onEvent, Key? key})
: super(key: key); : super(key: key);
@override @override
@ -371,17 +372,17 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
List<Widget> children = [ List<Widget> children = [
DateFormatButton(onTap: () { DateFormatButton(onTap: () {
final list = DateFormatList( final list = DateFormatList(
selectedFormat: widget.dateTypeOption.dateFormat, selectedFormat: widget.dateTypeOptionPB.dateFormat,
onSelected: (format) => onSelected: (format) =>
widget.onEvent(DateCalEvent.setDateFormat(format)), widget.onEvent(DateCalEvent.setDateFormat(format)),
); );
_showOverlay(context, list); _showOverlay(context, list);
}), }),
TimeFormatButton( TimeFormatButton(
timeFormat: widget.dateTypeOption.timeFormat, timeFormat: widget.dateTypeOptionPB.timeFormat,
onTap: () { onTap: () {
final list = TimeFormatList( final list = TimeFormatList(
selectedFormat: widget.dateTypeOption.timeFormat, selectedFormat: widget.dateTypeOptionPB.timeFormat,
onSelected: (format) => onSelected: (format) =>
widget.onEvent(DateCalEvent.setTimeFormat(format)), widget.onEvent(DateCalEvent.setTimeFormat(format)),
); );

View File

@ -59,7 +59,7 @@ class _SingleSelectCellState extends State<GridSingleSelectCell> {
value: _cellBloc, value: _cellBloc,
child: BlocBuilder<SelectOptionCellBloc, SelectOptionCellState>( child: BlocBuilder<SelectOptionCellBloc, SelectOptionCellState>(
builder: (context, state) { builder: (context, state) {
return _SelectOptionCell( return SelectOptionWrap(
selectOptions: state.selectedOptions, selectOptions: state.selectedOptions,
cellStyle: widget.cellStyle, cellStyle: widget.cellStyle,
onFocus: (value) => widget.onCellEditing.value = value, onFocus: (value) => widget.onCellEditing.value = value,
@ -115,11 +115,12 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
value: _cellBloc, value: _cellBloc,
child: BlocBuilder<SelectOptionCellBloc, SelectOptionCellState>( child: BlocBuilder<SelectOptionCellBloc, SelectOptionCellState>(
builder: (context, state) { builder: (context, state) {
return _SelectOptionCell( return SelectOptionWrap(
selectOptions: state.selectedOptions, selectOptions: state.selectedOptions,
cellStyle: widget.cellStyle, cellStyle: widget.cellStyle,
onFocus: (value) => widget.onCellEditing.value = value, onFocus: (value) => widget.onCellEditing.value = value,
cellControllerBuilder: widget.cellControllerBuilder); cellControllerBuilder: widget.cellControllerBuilder,
);
}, },
), ),
); );
@ -132,16 +133,16 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
} }
} }
class _SelectOptionCell extends StatelessWidget { class SelectOptionWrap extends StatelessWidget {
final List<SelectOptionPB> selectOptions; final List<SelectOptionPB> selectOptions;
final void Function(bool) onFocus; final void Function(bool)? onFocus;
final SelectOptionCellStyle? cellStyle; final SelectOptionCellStyle? cellStyle;
final GridCellControllerBuilder cellControllerBuilder; final GridCellControllerBuilder cellControllerBuilder;
const _SelectOptionCell({ const SelectOptionWrap({
required this.selectOptions, required this.selectOptions,
required this.onFocus,
required this.cellStyle,
required this.cellControllerBuilder, required this.cellControllerBuilder,
this.onFocus,
this.cellStyle,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -177,11 +178,11 @@ class _SelectOptionCell extends StatelessWidget {
child, child,
InkWell( InkWell(
onTap: () { onTap: () {
onFocus(true); onFocus?.call(true);
final cellContext = final cellContext =
cellControllerBuilder.build() as GridSelectOptionCellController; cellControllerBuilder.build() as GridSelectOptionCellController;
SelectOptionCellEditor.show( SelectOptionCellEditor.show(
context, cellContext, () => onFocus(false)); context, cellContext, () => onFocus?.call(false));
}, },
), ),
], ],

View File

@ -64,7 +64,7 @@ class _URLCellEditorState extends State<URLCellEditor> {
@override @override
void initState() { void initState() {
_cellBloc = URLCellEditorBloc(cellContext: widget.cellController); _cellBloc = URLCellEditorBloc(cellController: widget.cellController);
_cellBloc.add(const URLCellEditorEvent.initial()); _cellBloc.add(const URLCellEditorEvent.initial());
_controller = TextEditingController(text: _cellBloc.state.content); _controller = TextEditingController(text: _cellBloc.state.content);

View File

@ -92,7 +92,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
void initState() { void initState() {
final cellContext = final cellContext =
widget.cellControllerBuilder.build() as GridURLCellController; widget.cellControllerBuilder.build() as GridURLCellController;
_cellBloc = URLCellBloc(cellContext: cellContext); _cellBloc = URLCellBloc(cellController: cellContext);
_cellBloc.add(const URLCellEvent.initial()); _cellBloc.add(const URLCellEvent.initial());
super.initState(); super.initState();
} }

View File

@ -64,7 +64,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
switch (dataController.field.fieldType) { switch (dataController.field.fieldType) {
case FieldType.Checkbox: case FieldType.Checkbox:
return CheckboxTypeOptionWidgetBuilder( return CheckboxTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<CheckboxTypeOption>( makeTypeOptionContextWithDataController<CheckboxTypeOptionPB>(
gridId: gridId, gridId: gridId,
fieldType: fieldType, fieldType: fieldType,
dataController: dataController, dataController: dataController,
@ -72,7 +72,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
); );
case FieldType.DateTime: case FieldType.DateTime:
return DateTypeOptionWidgetBuilder( return DateTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<DateTypeOption>( makeTypeOptionContextWithDataController<DateTypeOptionPB>(
gridId: gridId, gridId: gridId,
fieldType: fieldType, fieldType: fieldType,
dataController: dataController, dataController: dataController,
@ -99,7 +99,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
); );
case FieldType.Number: case FieldType.Number:
return NumberTypeOptionWidgetBuilder( return NumberTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<NumberTypeOption>( makeTypeOptionContextWithDataController<NumberTypeOptionPB>(
gridId: gridId, gridId: gridId,
fieldType: fieldType, fieldType: fieldType,
dataController: dataController, dataController: dataController,
@ -108,7 +108,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
); );
case FieldType.RichText: case FieldType.RichText:
return RichTextTypeOptionWidgetBuilder( return RichTextTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<RichTextTypeOption>( makeTypeOptionContextWithDataController<RichTextTypeOptionPB>(
gridId: gridId, gridId: gridId,
fieldType: fieldType, fieldType: fieldType,
dataController: dataController, dataController: dataController,
@ -117,7 +117,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
case FieldType.URL: case FieldType.URL:
return URLTypeOptionWidgetBuilder( return URLTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<URLTypeOption>( makeTypeOptionContextWithDataController<URLTypeOptionPB>(
gridId: gridId, gridId: gridId,
fieldType: fieldType, fieldType: fieldType,
dataController: dataController, dataController: dataController,

View File

@ -170,33 +170,33 @@ void _resolveGridDeps(GetIt getIt) {
getIt.registerFactoryParam<TextCellBloc, GridCellController, void>( getIt.registerFactoryParam<TextCellBloc, GridCellController, void>(
(context, _) => TextCellBloc( (context, _) => TextCellBloc(
cellContext: context, cellController: context,
), ),
); );
getIt.registerFactoryParam<SelectOptionCellBloc, getIt.registerFactoryParam<SelectOptionCellBloc,
GridSelectOptionCellController, void>( GridSelectOptionCellController, void>(
(context, _) => SelectOptionCellBloc( (context, _) => SelectOptionCellBloc(
cellContext: context, cellController: context,
), ),
); );
getIt.registerFactoryParam<NumberCellBloc, GridCellController, void>( getIt.registerFactoryParam<NumberCellBloc, GridCellController, void>(
(context, _) => NumberCellBloc( (context, _) => NumberCellBloc(
cellContext: context, cellController: context,
), ),
); );
getIt.registerFactoryParam<DateCellBloc, GridDateCellController, void>( getIt.registerFactoryParam<DateCellBloc, GridDateCellController, void>(
(context, _) => DateCellBloc( (context, _) => DateCellBloc(
cellContext: context, cellController: context,
), ),
); );
getIt.registerFactoryParam<CheckboxCellBloc, GridCellController, void>( getIt.registerFactoryParam<CheckboxCellBloc, GridCellController, void>(
(cellData, _) => CheckboxCellBloc( (cellData, _) => CheckboxCellBloc(
service: CellService(), service: CellService(),
cellContext: cellData, cellController: cellData,
), ),
); );

View File

@ -87,7 +87,7 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
); );
} }
Widget _buildCard(ColumnItem item) { Widget _buildCard(AFColumnItem item) {
if (item is TextItem) { if (item is TextItem) {
return Align( return Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
@ -126,7 +126,7 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
} }
} }
class TextItem extends ColumnItem { class TextItem extends AFColumnItem {
final String s; final String s;
TextItem(this.s); TextItem(this.s);
@ -135,7 +135,7 @@ class TextItem extends ColumnItem {
String get id => s; String get id => s;
} }
class RichTextItem extends ColumnItem { class RichTextItem extends AFColumnItem {
final String title; final String title;
final String subtitle; final String subtitle;

View File

@ -50,7 +50,7 @@ class _RowWidget extends StatelessWidget {
} }
} }
class TextItem extends ColumnItem { class TextItem extends AFColumnItem {
final String s; final String s;
TextItem(this.s); TextItem(this.s);

View File

@ -24,7 +24,7 @@ typedef OnColumnInserted = void Function(String listId, int insertedIndex);
typedef AFBoardColumnCardBuilder = Widget Function( typedef AFBoardColumnCardBuilder = Widget Function(
BuildContext context, BuildContext context,
ColumnItem item, AFColumnItem item,
); );
typedef AFBoardColumnHeaderBuilder = Widget Function( typedef AFBoardColumnHeaderBuilder = Widget Function(
@ -46,7 +46,7 @@ abstract class AFBoardColumnDataDataSource extends ReoderFlextDataSource {
String get identifier => columnData.id; String get identifier => columnData.id;
@override @override
UnmodifiableListView<ColumnItem> get items => columnData.items; UnmodifiableListView<AFColumnItem> get items => columnData.items;
void debugPrint() { void debugPrint() {
String msg = '[$AFBoardColumnDataDataSource] $columnData data: '; String msg = '[$AFBoardColumnDataDataSource] $columnData data: ';
@ -194,7 +194,7 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
); );
} }
Widget _buildWidget(BuildContext context, ColumnItem item) { Widget _buildWidget(BuildContext context, AFColumnItem item) {
if (item is PhantomColumnItem) { if (item is PhantomColumnItem) {
return PassthroughPhantomWidget( return PassthroughPhantomWidget(
key: UniqueKey(), key: UniqueKey(),

View File

@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
import '../../utils/log.dart'; import '../../utils/log.dart';
import '../reorder_flex/reorder_flex.dart'; import '../reorder_flex/reorder_flex.dart';
abstract class ColumnItem extends ReoderFlexItem { abstract class AFColumnItem extends ReoderFlexItem {
bool get isPhantom => false; bool get isPhantom => false;
@override @override
@ -31,7 +31,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
List<Object?> get props => columnData.props; List<Object?> get props => columnData.props;
/// Returns the readonly List<ColumnItem> /// Returns the readonly List<ColumnItem>
UnmodifiableListView<ColumnItem> get items => UnmodifiableListView<AFColumnItem> get items =>
UnmodifiableListView(columnData.items); UnmodifiableListView(columnData.items);
/// Remove the item at [index]. /// Remove the item at [index].
@ -39,7 +39,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
/// * [notify] the default value of [notify] is true, it will notify the /// * [notify] the default value of [notify] is true, it will notify the
/// listener. Set to [false] if you do not want to notify the listeners. /// listener. Set to [false] if you do not want to notify the listeners.
/// ///
ColumnItem removeAt(int index, {bool notify = true}) { AFColumnItem removeAt(int index, {bool notify = true}) {
assert(index >= 0); assert(index >= 0);
Log.debug('[$BoardColumnDataController] $columnData remove item at $index'); Log.debug('[$BoardColumnDataController] $columnData remove item at $index');
@ -50,7 +50,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
return item; return item;
} }
int removeWhere(bool Function(ColumnItem) condition) { int removeWhere(bool Function(AFColumnItem) condition) {
return items.indexWhere(condition); return items.indexWhere(condition);
} }
@ -75,7 +75,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
/// is true. /// is true.
/// ///
/// The default value of [notify] is true. /// The default value of [notify] is true.
bool insert(int index, ColumnItem item, {bool notify = true}) { bool insert(int index, AFColumnItem item, {bool notify = true}) {
assert(index >= 0); assert(index >= 0);
Log.debug( Log.debug(
'[$BoardColumnDataController] $columnData insert $item at $index'); '[$BoardColumnDataController] $columnData insert $item at $index');
@ -90,14 +90,14 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
return true; return true;
} }
bool add(ColumnItem item, {bool notify = true}) { bool add(AFColumnItem item, {bool notify = true}) {
columnData._items.add(item); columnData._items.add(item);
if (notify) notifyListeners(); if (notify) notifyListeners();
return true; return true;
} }
/// Replace the item at index with the [newItem]. /// Replace the item at index with the [newItem].
void replace(int index, ColumnItem newItem) { void replace(int index, AFColumnItem newItem) {
if (columnData._items.isEmpty) { if (columnData._items.isEmpty) {
columnData._items.add(newItem); columnData._items.add(newItem);
Log.debug('[$BoardColumnDataController] $columnData add $newItem'); Log.debug('[$BoardColumnDataController] $columnData add $newItem');
@ -117,18 +117,18 @@ class AFBoardColumnData<CustomData> extends ReoderFlexItem with EquatableMixin {
@override @override
final String id; final String id;
final String desc; final String desc;
final List<ColumnItem> _items; final List<AFColumnItem> _items;
final CustomData? customData; final CustomData? customData;
AFBoardColumnData({ AFBoardColumnData({
this.customData, this.customData,
required this.id, required this.id,
this.desc = "", this.desc = "",
List<ColumnItem> items = const [], List<AFColumnItem> items = const [],
}) : _items = items; }) : _items = items;
/// Returns the readonly List<ColumnItem> /// Returns the readonly List<ColumnItem>
UnmodifiableListView<ColumnItem> get items => UnmodifiableListView(_items); UnmodifiableListView<AFColumnItem> get items => UnmodifiableListView(_items);
@override @override
List<Object?> get props => [id, ..._items]; List<Object?> get props => [id, ..._items];

View File

@ -110,11 +110,11 @@ class AFBoardDataController extends ChangeNotifier
} }
} }
void addColumnItem(String columnId, ColumnItem item) { void addColumnItem(String columnId, AFColumnItem item) {
getColumnController(columnId)?.add(item); getColumnController(columnId)?.add(item);
} }
void insertColumnItem(String columnId, int index, ColumnItem item) { void insertColumnItem(String columnId, int index, AFColumnItem item) {
getColumnController(columnId)?.insert(index, item); getColumnController(columnId)?.insert(index, item);
} }

View File

@ -253,7 +253,7 @@ class PhantomRecord {
} }
} }
class PhantomColumnItem extends ColumnItem { class PhantomColumnItem extends AFColumnItem {
final PassthroughPhantomContext phantomContext; final PassthroughPhantomContext phantomContext;
PhantomColumnItem(PassthroughPhantomContext insertedPhantom) PhantomColumnItem(PassthroughPhantomContext insertedPhantom)
@ -290,7 +290,7 @@ class PassthroughPhantomContext extends FakeDragTargetEventTrigger
Widget? get draggingWidget => dragTargetData.draggingWidget; Widget? get draggingWidget => dragTargetData.draggingWidget;
ColumnItem get itemData => dragTargetData.reorderFlexItem as ColumnItem; AFColumnItem get itemData => dragTargetData.reorderFlexItem as AFColumnItem;
@override @override
VoidCallback? onInserted; VoidCallback? onInserted;

View File

@ -86,9 +86,13 @@ where
match response.parse::<R, E>() { match response.parse::<R, E>() {
Ok(Ok(data)) => data, Ok(Ok(data)) => data,
Ok(Err(e)) => { Ok(Err(e)) => {
panic!("parse failed: {:?}", e) panic!("Parser {:?} failed: {:?}", std::any::type_name::<R>(), e)
} }
Err(e) => panic!("Internal error: {:?}", e), Err(e) => panic!(
"Internal error: {:?}, parser {:?} failed",
e,
std::any::type_name::<R>(),
),
} }
} }