chore: format number cell

This commit is contained in:
appflowy 2022-04-12 21:31:38 +08:00
parent 943b4507ac
commit a707410548
11 changed files with 101 additions and 167 deletions

View File

@ -156,13 +156,6 @@ void _resolveGridDeps(GetIt getIt) {
), ),
); );
getIt.registerFactoryParam<GridHeaderBloc, String, List<Field>>(
(gridId, fields) => GridHeaderBloc(
data: GridHeaderData(gridId: gridId, fields: fields),
service: FieldService(gridId: gridId),
),
);
getIt.registerFactoryParam<FieldActionSheetBloc, GridFieldCellContext, void>( getIt.registerFactoryParam<FieldActionSheetBloc, GridFieldCellContext, void>(
(data, _) => FieldActionSheetBloc( (data, _) => FieldActionSheetBloc(
field: data.field, field: data.field,

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart'; import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart';
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.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';
@ -11,12 +12,14 @@ part 'number_cell_bloc.freezed.dart';
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> { class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
final CellService _service; final CellService _service;
final CellListener _listener; final CellListener _cellListener;
final FieldListener _fieldListener;
NumberCellBloc({ NumberCellBloc({
required CellData cellData, required CellData cellData,
}) : _service = CellService(), }) : _service = CellService(),
_listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id), _cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
_fieldListener = FieldListener(fieldId: cellData.field.id),
super(NumberCellState.initial(cellData)) { super(NumberCellState.initial(cellData)) {
on<NumberCellEvent>( on<NumberCellEvent>(
(event, emit) async { (event, emit) async {
@ -27,36 +30,36 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
didReceiveCellUpdate: (_DidReceiveCellUpdate value) { didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
emit(state.copyWith(content: value.cell.content)); emit(state.copyWith(content: value.cell.content));
}, },
updateCell: (_UpdateCell value) { updateCell: (_UpdateCell value) async {
_updateCellValue(value, emit); await _updateCellValue(value, emit);
}, },
); );
}, },
); );
} }
void _updateCellValue(_UpdateCell value, Emitter<NumberCellState> emit) { Future<void> _updateCellValue(_UpdateCell value, Emitter<NumberCellState> emit) async {
final number = num.tryParse(value.text); final result = await _service.updateCell(
if (number == null) { gridId: state.cellData.gridId,
emit(state.copyWith(content: "")); fieldId: state.cellData.field.id,
} else { rowId: state.cellData.rowId,
_service.updateCell( data: value.text,
gridId: state.cellData.gridId, );
fieldId: state.cellData.field.id, result.fold(
rowId: state.cellData.rowId, (field) => _getCellData(),
data: value.text, (err) => Log.error(err),
); );
}
} }
@override @override
Future<void> close() async { Future<void> close() async {
await _listener.stop(); await _cellListener.stop();
await _fieldListener.stop();
return super.close(); return super.close();
} }
void _startListening() { void _startListening() {
_listener.updateCellNotifier.addPublishListener((result) { _cellListener.updateCellNotifier.addPublishListener((result) {
result.fold( result.fold(
(notificationData) async { (notificationData) async {
await _getCellData(); await _getCellData();
@ -64,7 +67,15 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
(err) => Log.error(err), (err) => Log.error(err),
); );
}); });
_listener.start(); _cellListener.start();
_fieldListener.updateFieldNotifier.addPublishListener((result) {
result.fold(
(field) => _getCellData(),
(err) => Log.error(err),
);
});
_fieldListener.start();
} }
Future<void> _getCellData() async { Future<void> _getCellData() async {

View File

@ -26,7 +26,13 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(field: value.field)); emit(state.copyWith(field: value.field));
}, },
updateWidth: (_UpdateWidth value) {}, updateWidth: (_UpdateWidth value) {
final defaultWidth = state.field.width.toDouble();
final width = defaultWidth + value.offset;
if (width > defaultWidth && width < 300) {
_fieldService.updateField(fieldId: state.field.id, width: width);
}
},
); );
}, },
); );

View File

@ -1,72 +0,0 @@
import 'package:app_flowy/workspace/application/grid/data.dart';
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'field_service.dart';
part 'grid_header_bloc.freezed.dart';
class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
final FieldService service;
final GridFieldsListener _fieldListener;
GridHeaderBloc({
required GridHeaderData data,
required this.service,
}) : _fieldListener = GridFieldsListener(gridId: data.gridId),
super(GridHeaderState.initial(data.fields)) {
on<GridHeaderEvent>(
(event, emit) async {
await event.map(
initial: (_InitialHeader value) async {
_startListening();
},
createField: (_CreateField value) {},
insertField: (_InsertField value) {},
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
value.fields.retainWhere((field) => field.visibility);
emit(state.copyWith(fields: value.fields));
},
);
},
);
}
Future<void> _startListening() async {
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
result.fold(
(fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)),
(err) => Log.error(err),
);
});
_fieldListener.start();
}
@override
Future<void> close() async {
await _fieldListener.stop();
return super.close();
}
}
@freezed
class GridHeaderEvent with _$GridHeaderEvent {
const factory GridHeaderEvent.initial() = _InitialHeader;
const factory GridHeaderEvent.createField() = _CreateField;
const factory GridHeaderEvent.insertField({required bool onLeft}) = _InsertField;
const factory GridHeaderEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
}
@freezed
class GridHeaderState with _$GridHeaderState {
const factory GridHeaderState({required List<Field> fields}) = _GridHeaderState;
factory GridHeaderState.initial(List<Field> fields) {
fields.retainWhere((field) => field.visibility);
return GridHeaderState(fields: fields);
}
}

View File

@ -6,7 +6,6 @@ export 'data.dart';
// Field // Field
export 'field/field_service.dart'; export 'field/field_service.dart';
export 'field/grid_header_bloc.dart';
export 'field/field_action_sheet_bloc.dart'; export 'field/field_action_sheet_bloc.dart';
export 'field/field_editor_bloc.dart'; export 'field/field_editor_bloc.dart';
export 'field/field_switch_bloc.dart'; export 'field/field_switch_bloc.dart';

View File

@ -85,7 +85,7 @@ class _FlowyGridState extends State<FlowyGrid> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<GridBloc, GridState>( return BlocBuilder<GridBloc, GridState>(
buildWhen: (previous, current) => previous.fields != current.fields, buildWhen: (previous, current) => previous.fields.length != current.fields.length,
builder: (context, state) { builder: (context, state) {
if (state.fields.isEmpty) { if (state.fields.isEmpty) {
return const Center(child: CircularProgressIndicator.adaptive()); return const Center(child: CircularProgressIndicator.adaptive());
@ -99,10 +99,10 @@ class _FlowyGridState extends State<FlowyGrid> {
physics: StyledScrollPhysics(), physics: StyledScrollPhysics(),
controller: _scrollController.verticalController, controller: _scrollController.verticalController,
slivers: [ slivers: [
_renderToolbar(state.gridId), const _GridToolbarAdaptor(),
_renderHeader(state.gridId), GridHeader(gridId: state.gridId, fields: List.from(state.fields)),
_renderRows(gridId: state.gridId, context: context), _GridRows(),
const GridFooter(), const SliverToBoxAdapter(child: GridFooter()),
], ],
), ),
), ),
@ -125,33 +125,35 @@ class _FlowyGridState extends State<FlowyGrid> {
), ),
); );
} }
}
Widget _renderHeader(String gridId) { class _GridToolbarAdaptor extends StatelessWidget {
return BlocSelector<GridBloc, GridState, List<Field>>( const _GridToolbarAdaptor({Key? key}) : super(key: key);
selector: (state) => state.fields,
builder: (context, fields) {
return GridHeader(gridId: gridId, fields: List.from(fields));
},
);
}
Widget _renderToolbar(String gridId) { @override
return BlocSelector<GridBloc, GridState, List<Field>>( Widget build(BuildContext context) {
selector: (state) => state.fields, return BlocSelector<GridBloc, GridState, GridToolbarContext>(
builder: (context, fields) { selector: (state) {
final toolbarContext = GridToolbarContext( return GridToolbarContext(
gridId: gridId, gridId: state.gridId,
fields: fields, fields: state.fields,
); );
},
builder: (context, toolbarContext) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: GridToolbar(toolbarContext: toolbarContext), child: GridToolbar(toolbarContext: toolbarContext),
); );
}, },
); );
} }
}
Widget _renderRows({required String gridId, required BuildContext context}) { class _GridRows extends StatelessWidget {
final _key = GlobalKey<SliverAnimatedListState>();
_GridRows({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocConsumer<GridBloc, GridState>( return BlocConsumer<GridBloc, GridState>(
listener: (context, state) { listener: (context, state) {
state.listState.map( state.listState.map(

View File

@ -26,7 +26,7 @@ class _NumberCellState extends State<NumberCell> {
@override @override
void initState() { void initState() {
_cellBloc = getIt<NumberCellBloc>(param1: widget.cellData); _cellBloc = getIt<NumberCellBloc>(param1: widget.cellData)..add(const NumberCellEvent.initial());
_controller = TextEditingController(text: _cellBloc.state.content); _controller = TextEditingController(text: _cellBloc.state.content);
_focusNode = CellFocusNode(); _focusNode = CellFocusNode();
super.initState(); super.initState();
@ -48,7 +48,6 @@ class _NumberCellState extends State<NumberCell> {
return TextField( return TextField(
controller: _controller, controller: _controller,
focusNode: _focusNode, focusNode: _focusNode,
onChanged: (value) => focusChanged(),
onEditingComplete: () => _focusNode.unfocus(), onEditingComplete: () => _focusNode.unfocus(),
maxLines: 1, maxLines: 1,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
@ -76,7 +75,12 @@ class _NumberCellState extends State<NumberCell> {
_delayOperation?.cancel(); _delayOperation?.cancel();
_delayOperation = Timer(const Duration(milliseconds: 300), () { _delayOperation = Timer(const Duration(milliseconds: 300), () {
if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) { if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) {
_cellBloc.add(NumberCellEvent.updateCell(_controller.text)); final number = num.tryParse(_controller.text);
if (number != null) {
_cellBloc.add(NumberCellEvent.updateCell(_controller.text));
} else {
_controller.text = "";
}
} }
}); });
} }

View File

@ -12,17 +12,15 @@ class GridFooter extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SliverToBoxAdapter( return SizedBox(
child: SizedBox( height: GridSize.footerHeight,
height: GridSize.footerHeight, child: Padding(
child: Padding( padding: GridSize.headerContentInsets,
padding: GridSize.headerContentInsets, child: Row(
child: Row( children: [
children: [ SizedBox(width: GridSize.leadingHeaderPadding),
SizedBox(width: GridSize.leadingHeaderPadding), const SizedBox(width: 120, child: _AddRowButton()),
const SizedBox(width: 120, child: _AddRowButton()), ],
],
),
), ),
), ),
); );

View File

@ -41,7 +41,7 @@ class GridFieldCell extends StatelessWidget {
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onHorizontalDragCancel: () {}, onHorizontalDragCancel: () {},
onHorizontalDragUpdate: (value) { onHorizontalDragUpdate: (value) {
Log.info(value.delta); context.read<FieldCellBloc>().add(FieldCellEvent.updateWidth(value.delta.dx));
}, },
child: FlowyHover( child: FlowyHover(
style: HoverStyle( style: HoverStyle(

View File

@ -19,21 +19,10 @@ class GridHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return SliverPersistentHeader(
create: (context) { delegate: _GridHeaderDelegate(gridId: gridId, fields: List.from(fields)),
final bloc = getIt<GridHeaderBloc>(param1: gridId, param2: fields); floating: true,
bloc.add(const GridHeaderEvent.initial()); pinned: true,
return bloc;
},
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) {
return SliverPersistentHeader(
delegate: _GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)),
floating: true,
pinned: true,
);
},
),
); );
} }
} }

View File

@ -74,21 +74,21 @@ class _StyledSingleChildScrollViewState extends State<StyledSingleChildScrollVie
} }
class StyledCustomScrollView extends StatefulWidget { class StyledCustomScrollView extends StatefulWidget {
final double? contentSize;
final Axis axis; final Axis axis;
final Color? trackColor; final Color? trackColor;
final Color? handleColor; final Color? handleColor;
final ScrollController? controller; final ScrollController? verticalController;
final List<Widget> slivers; final List<Widget> slivers;
final double barSize;
const StyledCustomScrollView({ const StyledCustomScrollView({
Key? key, Key? key,
this.contentSize,
this.axis = Axis.vertical, this.axis = Axis.vertical,
this.trackColor, this.trackColor,
this.handleColor, this.handleColor,
this.controller, this.verticalController,
this.slivers = const <Widget>[], this.slivers = const <Widget>[],
this.barSize = 12,
}) : super(key: key); }) : super(key: key);
@override @override
@ -96,17 +96,17 @@ class StyledCustomScrollView extends StatefulWidget {
} }
class _StyledCustomScrollViewState extends State<StyledCustomScrollView> { class _StyledCustomScrollViewState extends State<StyledCustomScrollView> {
late ScrollController scrollController; late ScrollController controller;
@override @override
void initState() { void initState() {
scrollController = widget.controller ?? ScrollController(); controller = widget.verticalController ?? ScrollController();
super.initState(); super.initState();
} }
@override @override
void dispose() { void dispose() {
scrollController.dispose();
super.dispose(); super.dispose();
} }
@ -120,19 +120,23 @@ class _StyledCustomScrollViewState extends State<StyledCustomScrollView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ScrollbarListStack( var child = ScrollConfiguration(
contentSize: widget.contentSize, behavior: const ScrollBehavior().copyWith(scrollbars: false),
axis: widget.axis,
controller: scrollController,
barSize: 12,
trackColor: widget.trackColor,
handleColor: widget.handleColor,
child: CustomScrollView( child: CustomScrollView(
scrollDirection: widget.axis, scrollDirection: widget.axis,
physics: StyledScrollPhysics(), physics: StyledScrollPhysics(),
controller: scrollController, controller: controller,
slivers: widget.slivers, slivers: widget.slivers,
), ),
); );
return ScrollbarListStack(
axis: widget.axis,
controller: controller,
barSize: widget.barSize,
trackColor: widget.trackColor,
handleColor: widget.handleColor,
child: child,
);
} }
} }