fix: grid header cell refresh after field was changed

This commit is contained in:
appflowy 2022-04-08 22:38:38 +08:00
parent fc77e0857a
commit fc4ed6c057
6 changed files with 107 additions and 29 deletions

View File

@ -0,0 +1,66 @@
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
part 'field_cell_bloc.freezed.dart';
class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
final FieldListener _fieldListener;
FieldCellBloc({
required GridFieldCellContext cellContext,
}) : _fieldListener = FieldListener(fieldId: cellContext.field.id),
super(FieldCellState.initial(cellContext)) {
on<FieldCellEvent>(
(event, emit) async {
await event.map(
initial: (_InitialCell value) async {
_startListening();
},
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(field: value.field));
},
);
},
);
}
@override
Future<void> close() async {
await _fieldListener.stop();
return super.close();
}
void _startListening() {
_fieldListener.updateFieldNotifier.addPublishListener((result) {
result.fold(
(field) => add(FieldCellEvent.didReceiveFieldUpdate(field)),
(err) => Log.error(err),
);
});
_fieldListener.start();
}
}
@freezed
class FieldCellEvent with _$FieldCellEvent {
const factory FieldCellEvent.initial() = _InitialCell;
const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
}
@freezed
class FieldCellState with _$FieldCellState {
const factory FieldCellState({
required String gridId,
required Field field,
}) = _FieldCellState;
factory FieldCellState.initial(GridFieldCellContext cellContext) => FieldCellState(
gridId: cellContext.gridId,
field: cellContext.field,
);
}

View File

@ -1,3 +1,4 @@
import 'package:app_flowy/workspace/application/grid/field/field_cell_bloc.dart';
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:flowy_infra/image.dart';
@ -12,46 +13,55 @@ import 'field_cell_action_sheet.dart';
import 'field_editor.dart';
class GridFieldCell extends StatelessWidget {
final GridFieldCellContext fieldCellContext;
const GridFieldCell(this.fieldCellContext, {Key? key}) : super(key: key);
final GridFieldCellContext cellContext;
const GridFieldCell(this.cellContext, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final field = fieldCellContext.field;
final button = FlowyButton(
hoverColor: theme.hover,
onTap: () => _showActionSheet(context),
rightIcon: svgWidget("editor/details", color: theme.iconColor),
leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
text: FlowyText.medium(field.name, fontSize: 12),
padding: GridSize.cellContentInsets,
);
return BlocProvider(
create: (context) => FieldCellBloc(cellContext: cellContext)..add(const FieldCellEvent.initial()),
child: BlocBuilder<FieldCellBloc, FieldCellState>(
builder: (context, state) {
final button = FlowyButton(
hoverColor: theme.hover,
onTap: () => _showActionSheet(context),
rightIcon: svgWidget("editor/details", color: theme.iconColor),
leftIcon: svgWidget(state.field.fieldType.iconName(), color: theme.iconColor),
text: FlowyText.medium(state.field.name, fontSize: 12),
padding: GridSize.cellContentInsets,
);
final borderSide = BorderSide(color: theme.shader4, width: 0.4);
final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide));
final borderSide = BorderSide(color: theme.shader4, width: 0.4);
final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide));
return Container(
width: field.width.toDouble(),
decoration: decoration,
child: button,
return Container(
width: state.field.width.toDouble(),
decoration: decoration,
child: button,
);
},
),
);
}
void _showActionSheet(BuildContext context) {
final state = context.read<FieldCellBloc>().state;
GridFieldCellActionSheet(
fieldCellContext: fieldCellContext,
cellContext: GridFieldCellContext(gridId: state.gridId, field: state.field),
onEdited: () => _showFieldEditor(context),
).show(context);
}
void _showFieldEditor(BuildContext context) {
final state = context.read<FieldCellBloc>().state;
FieldEditor(
gridId: fieldCellContext.gridId,
gridId: state.gridId,
fieldContextLoader: FieldContextLoaderAdaptor(
gridId: fieldCellContext.gridId,
field: fieldCellContext.field,
gridId: state.gridId,
field: state.field,
),
).show(context);
}

View File

@ -13,9 +13,9 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate {
final GridFieldCellContext fieldCellContext;
final GridFieldCellContext cellContext;
final VoidCallback onEdited;
const GridFieldCellActionSheet({required this.fieldCellContext, required this.onEdited, Key? key}) : super(key: key);
const GridFieldCellActionSheet({required this.cellContext, required this.onEdited, Key? key}) : super(key: key);
void show(BuildContext overlayContext) {
FlowyOverlay.of(overlayContext).insertWithAnchor(
@ -33,7 +33,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => getIt<FieldActionSheetBloc>(param1: fieldCellContext),
create: (context) => getIt<FieldActionSheetBloc>(param1: cellContext),
child: SingleChildScrollView(
child: Column(
children: [
@ -44,7 +44,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate
},
),
const VSpace(6),
_FieldOperationList(fieldCellContext, () => FlowyOverlay.of(context).remove(identifier())),
_FieldOperationList(cellContext, () => FlowyOverlay.of(context).remove(identifier())),
],
),
),

View File

@ -58,7 +58,7 @@ class _GridHeaderDelegate extends SliverPersistentHeaderDelegate {
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
if (oldDelegate is _GridHeaderDelegate) {
return fields != oldDelegate.fields;
return fields.length != oldDelegate.fields.length;
}
return true;
}

View File

@ -8,7 +8,7 @@ edition = "2018"
name = "dart_ffi"
# this value will change depending on the target os
# default static lib
crate-type = ["staticlib"]
crate-type = ["cdylib"]
[dependencies]

View File

@ -58,7 +58,7 @@ impl ClientGridEditor {
start_field_id,
grid_id,
} = params;
let field_id = field.id.clone();
let _ = self
.modify(|grid| {
if grid.contain_field(&field.id) {
@ -84,6 +84,7 @@ impl ClientGridEditor {
})
.await?;
let _ = self.notify_did_update_grid().await?;
let _ = self.notify_did_update_field(&field_id).await?;
Ok(())
}
@ -409,12 +410,13 @@ impl ClientGridEditor {
Ok(())
}
#[tracing::instrument(level = "trace", skip_all, err)]
async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> {
let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?;
debug_assert!(field_metas.len() == 1);
if let Some(field_meta) = field_metas.pop() {
send_dart_notification(&self.grid_id, GridNotification::DidUpdateField)
send_dart_notification(&field_id, GridNotification::DidUpdateField)
.payload(field_meta)
.send();
}