chore: show and hide property

This commit is contained in:
appflowy 2022-04-03 20:29:06 +08:00
parent 6a94594a35
commit aa9e3d065b
5 changed files with 98 additions and 48 deletions

View File

@ -1,40 +1,66 @@
import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.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';
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 'dart:async'; import 'dart:async';
import 'package:dartz/dartz.dart';
part 'property_bloc.freezed.dart'; part 'property_bloc.freezed.dart';
class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> { class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {
final FieldService _service; final FieldService _service;
final GridFieldsListener _fieldListener;
GridPropertyBloc({required String gridId, required List<Field> fields}) GridPropertyBloc({required String gridId, required List<Field> fields})
: _service = FieldService(gridId: gridId), : _service = FieldService(gridId: gridId),
_fieldListener = GridFieldsListener(gridId: gridId),
super(GridPropertyState.initial(gridId, fields)) { super(GridPropertyState.initial(gridId, fields)) {
on<GridPropertyEvent>( on<GridPropertyEvent>(
(event, emit) async { (event, emit) async {
await event.map(setFieldVisibility: (_SetFieldVisibility value) async { await event.map(
final result = await _service.updateField(fieldId: value.fieldId, visibility: value.visibility); initial: (_Initial value) {
result.fold( _startListening();
(l) => null, },
(err) => Log.error(err), setFieldVisibility: (_SetFieldVisibility value) async {
); final result = await _service.updateField(fieldId: value.fieldId, visibility: value.visibility);
}); result.fold(
(l) => null,
(err) => Log.error(err),
);
},
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(fields: value.fields));
},
);
}, },
); );
} }
@override @override
Future<void> close() async { Future<void> close() async {
await _fieldListener.stop();
return super.close(); return super.close();
} }
void _startListening() {
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
result.fold(
(fields) {
add(GridPropertyEvent.didReceiveFieldUpdate(fields));
},
(err) => Log.error(err),
);
});
_fieldListener.start();
}
} }
@freezed @freezed
class GridPropertyEvent with _$GridPropertyEvent { class GridPropertyEvent with _$GridPropertyEvent {
const factory GridPropertyEvent.initial() = _Initial;
const factory GridPropertyEvent.setFieldVisibility(String fieldId, bool visibility) = _SetFieldVisibility; const factory GridPropertyEvent.setFieldVisibility(String fieldId, bool visibility) = _SetFieldVisibility;
const factory GridPropertyEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
} }
@freezed @freezed

View File

@ -148,11 +148,13 @@ class _FlowyGridState extends State<FlowyGrid> {
return BlocBuilder<GridBloc, GridState>( return BlocBuilder<GridBloc, GridState>(
buildWhen: (previous, current) => previous.fields.length != current.fields.length, buildWhen: (previous, current) => previous.fields.length != current.fields.length,
builder: (context, state) { builder: (context, state) {
return SliverPersistentHeader( return GridHeader(gridId: gridId, fields: List.from(state.fields));
delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)),
floating: true, // return SliverPersistentHeader(
pinned: true, // delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)),
); // floating: true,
// pinned: true,
// );
}, },
); );
} }

View File

@ -38,7 +38,7 @@ class _NumberCellState extends State<NumberCell> {
@override @override
Future<void> dispose() async { Future<void> dispose() async {
await _cellBloc.close(); _cellBloc.close();
super.dispose(); super.dispose();
} }
} }

View File

@ -12,15 +12,41 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'field_editor.dart'; import 'field_editor.dart';
import 'field_cell.dart'; import 'field_cell.dart';
class GridHeaderDelegate extends SliverPersistentHeaderDelegate { class GridHeader extends StatelessWidget {
final String gridId;
final List<Field> fields;
const GridHeader({Key? key, required this.gridId, required this.fields}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
final bloc = getIt<GridHeaderBloc>(param1: gridId, param2: fields);
bloc.add(const GridHeaderEvent.initial());
return bloc;
},
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) {
return SliverPersistentHeader(
delegate: _GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)),
floating: true,
pinned: true,
);
},
),
);
}
}
class _GridHeaderDelegate extends SliverPersistentHeaderDelegate {
final String gridId; final String gridId;
final List<Field> fields; final List<Field> fields;
GridHeaderDelegate({required this.gridId, required this.fields}); _GridHeaderDelegate({required this.gridId, required this.fields});
@override @override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields)); return _GridHeaderWidget(gridId: gridId, fields: fields, key: ObjectKey(fields));
} }
@override @override
@ -31,47 +57,42 @@ class GridHeaderDelegate extends SliverPersistentHeaderDelegate {
@override @override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
if (oldDelegate is GridHeaderDelegate) { if (oldDelegate is _GridHeaderDelegate) {
return fields != oldDelegate.fields; return fields != oldDelegate.fields;
} }
return false; return true;
} }
} }
class GridHeader extends StatelessWidget { class _GridHeaderWidget extends StatelessWidget {
final List<Field> fields;
final String gridId; final String gridId;
const GridHeader({required this.gridId, required this.fields, Key? key}) : super(key: key); final List<Field> fields;
const _GridHeaderWidget({required this.gridId, required this.fields, 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>();
return BlocProvider( return BlocBuilder<GridHeaderBloc, GridHeaderState>(
create: (context) { builder: (context, state) {
final bloc = getIt<GridHeaderBloc>(param1: gridId, param2: fields); final cells = state.fields.map(
bloc.add(const GridHeaderEvent.initial()); (field) => GridFieldCell(
return bloc; GridFieldCellContext(gridId: gridId, field: field),
),
);
final row = Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const _HeaderLeading(),
...cells,
_HeaderTrailing(gridId: gridId),
],
key: UniqueKey(),
);
return Container(height: GridSize.headerHeight, color: theme.surface, child: row);
}, },
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) {
final cells = state.fields.map(
(field) => GridFieldCell(
GridFieldCellContext(gridId: gridId, field: field),
),
);
final row = Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const _HeaderLeading(),
...cells,
_HeaderTrailing(gridId: gridId),
],
);
return Container(color: theme.surface, child: row);
},
),
); );
} }
} }

View File

@ -42,7 +42,8 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => getIt<GridPropertyBloc>(param1: gridId, param2: fields), create: (context) =>
getIt<GridPropertyBloc>(param1: gridId, param2: fields)..add(const GridPropertyEvent.initial()),
child: BlocBuilder<GridPropertyBloc, GridPropertyState>( child: BlocBuilder<GridPropertyBloc, GridPropertyState>(
builder: (context, state) { builder: (context, state) {
final cells = state.fields.map((field) { final cells = state.fields.map((field) {