diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart index e2e7f2f0e2..0cf842a171 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart @@ -2,7 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - +import 'package:protobuf/protobuf.dart'; part 'date_bloc.freezed.dart'; class DateTypeOptionBloc extends Bloc { @@ -11,18 +11,30 @@ class DateTypeOptionBloc extends Bloc (event, emit) async { event.map( didSelectDateFormat: (_DidSelectDateFormat value) { - state.typeOption.dateFormat = value.format; - emit(state); + emit(state.copyWith(typeOption: _updateDateFormat(value.format))); }, didSelectTimeFormat: (_DidSelectTimeFormat value) { - state.typeOption.timeFormat = value.format; - emit(state); + emit(state.copyWith(typeOption: _updateTimeFormat(value.format))); }, ); }, ); } + DateTypeOption _updateTimeFormat(TimeFormat format) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + typeOption.timeFormat = format; + }); + } + + DateTypeOption _updateDateFormat(DateFormat format) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + typeOption.dateFormat = format; + }); + } + @override Future close() async { return super.close(); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart index a396454671..a655ebc1e8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart @@ -2,6 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; +import 'package:protobuf/protobuf.dart'; part 'number_bloc.freezed.dart'; @@ -11,14 +12,20 @@ class NumberTypeOptionBloc extends Bloc close() async { return super.close(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart deleted file mode 100644 index cab5a51138..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart +++ /dev/null @@ -1,110 +0,0 @@ -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'field_name_input.dart'; -import 'field_operation_list.dart'; -import 'field_tyep_switcher.dart'; - -class EditFieldPannel extends StatelessWidget { - final GridFieldData fieldData; - const EditFieldPannel({required this.fieldData, Key? key}) : super(key: key); - - static void show(BuildContext context, GridFieldData fieldData) { - final editor = EditFieldPannel(fieldData: fieldData); - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - child: editor, - constraints: BoxConstraints.loose(const Size(300, 200)), - ), - identifier: editor.identifier(), - anchorContext: context, - anchorDirection: AnchorDirection.bottomWithLeftAligned, - ); - } - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(param1: fieldData)..add(const EditFieldEvent.initial()), - child: SingleChildScrollView( - child: Column( - children: [ - const _FieldNameTextField(), - const VSpace(6), - const _FieldTypeSwitcher(), - const VSpace(6), - _FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())), - ], - ), - ), - ); - } - - String identifier() { - return toString(); - } -} - -class _FieldOperationList extends StatelessWidget { - final GridFieldData fieldData; - final VoidCallback onDismissed; - const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final actions = FieldAction.values - .map( - (action) => FieldActionItem( - fieldId: fieldData.field.id, - action: action, - onTap: onDismissed, - ), - ) - .toList(); - - return FieldOperationList(actions: actions); - } -} - -class _FieldTypeSwitcher extends StatelessWidget { - const _FieldTypeSwitcher({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final editContext = context.read().state.editContext; - final switchContext = SwitchFieldContext( - editContext.gridId, - editContext.gridField, - editContext.typeOptionData, - ); - return FieldTypeSwitcher(switchContext: switchContext, onSelected: (field, typeOptionData) {}); - }, - ); - } -} - -class _FieldNameTextField extends StatelessWidget { - const _FieldNameTextField({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: ((previous, current) => previous.fieldName == current.fieldName), - builder: (context, state) { - return FieldNameTextField( - name: state.fieldName, - errorText: state.errorText, - onNameChanged: (newName) { - context.read().add(EditFieldEvent.updateFieldName(newName)); - }, - ); - }, - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart index 5e5dc5f4fd..19869ccffc 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart @@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'edit_field_pannel.dart'; +import 'field_detail_pannel.dart'; class GridHeaderCell extends StatelessWidget { final GridFieldData fieldData; @@ -18,7 +18,7 @@ class GridHeaderCell extends StatelessWidget { final theme = context.watch(); final button = FlowyButton( hoverColor: theme.hover, - onTap: () => EditFieldPannel.show(context, fieldData), + onTap: () => FieldDetailPannel.show(context, fieldData), rightIcon: svg("editor/details", color: theme.iconColor), text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index 581a3934e7..0a057b5727 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -50,15 +50,15 @@ class DateTypeOptionWidget extends TypeOptionWidget { listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), builder: (context, state) { return Column(children: [ - _dateFormatButton(context), - _timeFormatButton(context), + _dateFormatButton(context, state.typeOption.dateFormat), + _timeFormatButton(context, state.typeOption.timeFormat), ]); }, ), ); } - Widget _dateFormatButton(BuildContext context) { + Widget _dateFormatButton(BuildContext context, DateFormat dataFormat) { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, @@ -67,9 +67,12 @@ class DateTypeOptionWidget extends TypeOptionWidget { padding: GridSize.typeOptionContentInsets, hoverColor: theme.hover, onTap: () { - final list = DateFormatList(onSelected: (format) { - context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); - }); + final list = DateFormatList( + selectedFormat: dataFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); + }, + ); overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), @@ -77,7 +80,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { ); } - Widget _timeFormatButton(BuildContext context) { + Widget _timeFormatButton(BuildContext context, TimeFormat timeFormat) { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, @@ -86,9 +89,11 @@ class DateTypeOptionWidget extends TypeOptionWidget { padding: GridSize.typeOptionContentInsets, hoverColor: theme.hover, onTap: () { - final list = TimeFormatList(onSelected: (format) { - context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); - }); + final list = TimeFormatList( + selectedFormat: timeFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); + }); overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), @@ -98,8 +103,9 @@ class DateTypeOptionWidget extends TypeOptionWidget { } class DateFormatList extends StatelessWidget { + final DateFormat selectedFormat; final Function(DateFormat format) onSelected; - const DateFormatList({required this.onSelected, Key? key}) : super(key: key); + const DateFormatList({required this.selectedFormat, required this.onSelected, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -109,7 +115,8 @@ class DateFormatList extends StatelessWidget { onSelected: (format) { onSelected(format); FlowyOverlay.of(context).remove(identifier()); - }); + }, + isSelected: selectedFormat == format); }).toList(); return SizedBox( @@ -134,18 +141,30 @@ class DateFormatList extends StatelessWidget { } class DateFormatItem extends StatelessWidget { + final bool isSelected; final DateFormat dateFormat; final Function(DateFormat format) onSelected; - const DateFormatItem({required this.dateFormat, required this.onSelected, Key? key}) : super(key: key); + const DateFormatItem({ + required this.dateFormat, + required this.onSelected, + required this.isSelected, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); + Widget? checkmark; + if (isSelected) { + checkmark = svg("grid/checkmark"); + } + return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(dateFormat.title(), fontSize: 12), hoverColor: theme.hover, + rightIcon: checkmark, onTap: () => onSelected(dateFormat), ), ); @@ -170,13 +189,19 @@ extension DateFormatExtension on DateFormat { } class TimeFormatList extends StatelessWidget { + final TimeFormat selectedFormat; final Function(TimeFormat format) onSelected; - const TimeFormatList({required this.onSelected, Key? key}) : super(key: key); + const TimeFormatList({ + required this.selectedFormat, + required this.onSelected, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final formatItems = TimeFormat.values.map((format) { return TimeFormatItem( + isSelected: format == selectedFormat, timeFormat: format, onSelected: (format) { onSelected(format); @@ -207,17 +232,29 @@ class TimeFormatList extends StatelessWidget { class TimeFormatItem extends StatelessWidget { final TimeFormat timeFormat; + final bool isSelected; final Function(TimeFormat format) onSelected; - const TimeFormatItem({required this.timeFormat, required this.onSelected, Key? key}) : super(key: key); + const TimeFormatItem({ + required this.timeFormat, + required this.onSelected, + required this.isSelected, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); + Widget? checkmark; + if (isSelected) { + checkmark = svg("grid/checkmark"); + } + return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(timeFormat.title(), fontSize: 12), hoverColor: theme.hover, + rightIcon: checkmark, onTap: () => onSelected(timeFormat), ), );