Merge branch 'main' into feat/wrap-appflowy-style-popover

This commit is contained in:
appflowy 2022-09-15 21:42:31 +08:00
commit 5294d7700e
32 changed files with 412 additions and 155 deletions

View File

@ -1,5 +1,27 @@
# Release Notes # Release Notes
## Version 0.0.5.1 - 09/14/2022
New features
- Enable deleting a field in board
- Fix some bugs
## Version 0.0.5 - 09/08/2022
New Features - Kanban Board like Notion and Trello beta
Boards are the best way to manage projects & tasks. Use them to group your databases by select, multiselect, and checkbox.
<p align="left"><img src="https://user-images.githubusercontent.com/12026239/190055984-6efa2d7a-ee38-4551-859e-ee56388e1859.gif" width="1000px" /></p>
- Set up columns that represent a specific phase of the project cycle and use cards to represent each project / task
- Drag and drop a card from one phase / column to another phase / column
- Update database properties in the Board view by clicking on a property and making edits on the card
### Other Features & Improvements
- Settings allow users to change avatars
- Click and drag the right edge to resize your sidebar
- And many user interface improvements (link)
## Version 0.0.5 - beta.2 - beta.1 - 09/01/2022 ## Version 0.0.5 - beta.2 - beta.1 - 09/01/2022
New features New features

View File

@ -22,7 +22,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi" CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi" CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi" LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.0.5" CURRENT_APP_VERSION = "0.0.5.1"
FEATURES = "flutter" FEATURES = "flutter"
PRODUCT_NAME = "AppFlowy" PRODUCT_NAME = "AppFlowy"
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html # CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html

View File

@ -191,7 +191,8 @@
"optionTitle": "Options", "optionTitle": "Options",
"addOption": "Add option", "addOption": "Add option",
"editProperty": "Edit property", "editProperty": "Edit property",
"newColumn": "New column" "newColumn": "New column",
"deleteFieldPromptMessage": "Are you sure? This property will be deleted"
}, },
"row": { "row": {
"duplicate": "Duplicate", "duplicate": "Duplicate",

View File

@ -287,8 +287,13 @@ class _BoardContentState extends State<BoardContent> {
); );
} }
void _openCard(String gridId, GridFieldController fieldController, void _openCard(
RowPB rowPB, GridRowCache rowCache, BuildContext context) { String gridId,
GridFieldController fieldController,
RowPB rowPB,
GridRowCache rowCache,
BuildContext context,
) {
final rowInfo = RowInfo( final rowInfo = RowInfo(
gridId: gridId, gridId: gridId,
fields: UnmodifiableListView(fieldController.fieldContexts), fields: UnmodifiableListView(fieldController.fieldContexts),

View File

@ -2,7 +2,9 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/plugins/board/application/toolbar/board_setting_bloc.dart'; import 'package:app_flowy/plugins/board/application/toolbar/board_setting_bloc.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_group.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart';
import 'package:appflowy_popover/popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
@ -141,10 +143,12 @@ extension _GridSettingExtension on BoardSettingAction {
} }
class BoardSettingListPopover extends StatefulWidget { class BoardSettingListPopover extends StatefulWidget {
final PopoverController popoverController;
final BoardSettingContext settingContext; final BoardSettingContext settingContext;
const BoardSettingListPopover({ const BoardSettingListPopover({
Key? key, Key? key,
required this.popoverController,
required this.settingContext, required this.settingContext,
}) : super(key: key); }) : super(key: key);
@ -153,36 +157,33 @@ class BoardSettingListPopover extends StatefulWidget {
} }
class _BoardSettingListPopoverState extends State<BoardSettingListPopover> { class _BoardSettingListPopoverState extends State<BoardSettingListPopover> {
bool _showGridPropertyList = false; BoardSettingAction? _action;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_showGridPropertyList) { if (_action != null) {
return OverlayContainer( switch (_action!) {
constraints: BoxConstraints.loose(const Size(260, 400)), case BoardSettingAction.groups:
child: GridPropertyList( return GridGroupList(
viewId: widget.settingContext.viewId,
fieldController: widget.settingContext.fieldController,
onDismissed: () {
widget.popoverController.close();
},
);
case BoardSettingAction.properties:
return GridPropertyList(
gridId: widget.settingContext.viewId, gridId: widget.settingContext.viewId,
fieldController: widget.settingContext.fieldController, fieldController: widget.settingContext.fieldController,
),
); );
} }
}
return OverlayContainer( return BoardSettingList(
constraints: BoxConstraints.loose(const Size(140, 400)),
child: BoardSettingList(
settingContext: widget.settingContext, settingContext: widget.settingContext,
onAction: (action, settingContext) { onAction: (action, settingContext) {
switch (action) { setState(() => _action = action);
case BoardSettingAction.groups:
break;
case BoardSettingAction.properties:
setState(() {
_showGridPropertyList = true;
});
break;
}
}, },
),
); );
} }
} }

View File

@ -2,6 +2,7 @@ import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:appflowy_popover/popover.dart'; import 'package:appflowy_popover/popover.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -40,15 +41,30 @@ class BoardToolbar extends StatelessWidget {
} }
} }
class _SettingButton extends StatelessWidget { class _SettingButton extends StatefulWidget {
final BoardSettingContext settingContext; final BoardSettingContext settingContext;
const _SettingButton({required this.settingContext, Key? key}) const _SettingButton({required this.settingContext, Key? key})
: super(key: key); : super(key: key);
@override
State<_SettingButton> createState() => _SettingButtonState();
}
class _SettingButtonState extends State<_SettingButton> {
late PopoverController popoverController;
@override
void initState() {
popoverController = PopoverController();
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.read<AppTheme>(); final theme = context.read<AppTheme>();
return Popover( return AppFlowyStylePopover(
controller: popoverController,
constraints: BoxConstraints.loose(const Size(260, 400)),
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
child: FlowyIconButton( child: FlowyIconButton(
hoverColor: theme.hover, hoverColor: theme.hover,
@ -61,7 +77,8 @@ class _SettingButton extends StatelessWidget {
), ),
popupBuilder: (BuildContext popoverContext) { popupBuilder: (BuildContext popoverContext) {
return BoardSettingListPopover( return BoardSettingListPopover(
settingContext: settingContext, settingContext: widget.settingContext,
popoverController: popoverController,
); );
}, },
); );

View File

@ -186,7 +186,8 @@ class DocumentShareButton extends StatelessWidget {
'Exported to: ${LocaleKeys.notifications_export_path.tr()}'); 'Exported to: ${LocaleKeys.notifications_export_path.tr()}');
break; break;
case ShareAction.copyLink: case ShareAction.copyLink:
FlowyAlertDialog(title: LocaleKeys.shareAction_workInProgress.tr()) NavigatorAlertDialog(
title: LocaleKeys.shareAction_workInProgress.tr())
.show(context); .show(context);
break; break;
} }

View File

@ -84,7 +84,7 @@ class FlowyLinkStyleButtonState extends State<FlowyLinkStyleButton> {
value = values.first; value = values.first;
} }
TextFieldDialog( NavigatorTextFieldDialog(
title: 'URL', title: 'URL',
value: value, value: value,
confirm: (newValue) { confirm: (newValue) {

View File

@ -2,6 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:async'; import 'dart:async';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'field_service.dart';
import 'type_option/type_option_context.dart'; import 'type_option/type_option_context.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
@ -15,10 +16,11 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
FieldEditorBloc({ FieldEditorBloc({
required String gridId, required String gridId,
required String fieldName, required String fieldName,
required bool isGroupField,
required IFieldTypeOptionLoader loader, required IFieldTypeOptionLoader loader,
}) : dataController = }) : dataController =
TypeOptionDataController(gridId: gridId, loader: loader), TypeOptionDataController(gridId: gridId, loader: loader),
super(FieldEditorState.initial(gridId, fieldName)) { super(FieldEditorState.initial(gridId, fieldName, isGroupField)) {
on<FieldEditorEvent>( on<FieldEditorEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
@ -35,7 +37,23 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
emit(state.copyWith(name: name)); emit(state.copyWith(name: name));
}, },
didReceiveFieldChanged: (FieldPB field) { didReceiveFieldChanged: (FieldPB field) {
emit(state.copyWith(field: Some(field), name: field.name)); emit(state.copyWith(
field: Some(field),
name: field.name,
canDelete: field.isPrimary,
));
},
deleteField: () {
state.field.fold(
() => null,
(field) {
final fieldService = FieldService(
gridId: gridId,
fieldId: field.id,
);
fieldService.deleteField();
},
);
}, },
); );
}, },
@ -52,6 +70,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
class FieldEditorEvent with _$FieldEditorEvent { class FieldEditorEvent with _$FieldEditorEvent {
const factory FieldEditorEvent.initial() = _InitialField; const factory FieldEditorEvent.initial() = _InitialField;
const factory FieldEditorEvent.updateName(String name) = _UpdateName; const factory FieldEditorEvent.updateName(String name) = _UpdateName;
const factory FieldEditorEvent.deleteField() = _DeleteField;
const factory FieldEditorEvent.didReceiveFieldChanged(FieldPB field) = const factory FieldEditorEvent.didReceiveFieldChanged(FieldPB field) =
_DidReceiveFieldChanged; _DidReceiveFieldChanged;
} }
@ -63,16 +82,21 @@ class FieldEditorState with _$FieldEditorState {
required String errorText, required String errorText,
required String name, required String name,
required Option<FieldPB> field, required Option<FieldPB> field,
required bool canDelete,
required bool isGroupField,
}) = _FieldEditorState; }) = _FieldEditorState;
factory FieldEditorState.initial( factory FieldEditorState.initial(
String gridId, String gridId,
String fieldName, String fieldName,
bool isGroupField,
) => ) =>
FieldEditorState( FieldEditorState(
gridId: gridId, gridId: gridId,
errorText: '', errorText: '',
field: none(), field: none(),
canDelete: false,
name: fieldName, name: fieldName,
isGroupField: isGroupField,
); );
} }

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.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';
@ -24,6 +25,13 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
didReceiveCellDatas: (_DidReceiveCellDatas value) { didReceiveCellDatas: (_DidReceiveCellDatas value) {
emit(state.copyWith(gridCells: value.gridCells)); emit(state.copyWith(gridCells: value.gridCells));
}, },
deleteField: (_DeleteField value) {
final fieldService = FieldService(
gridId: dataController.rowInfo.gridId,
fieldId: value.fieldId,
);
fieldService.deleteField();
},
); );
}, },
); );
@ -49,6 +57,7 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
@freezed @freezed
class RowDetailEvent with _$RowDetailEvent { class RowDetailEvent with _$RowDetailEvent {
const factory RowDetailEvent.initial() = _Initial; const factory RowDetailEvent.initial() = _Initial;
const factory RowDetailEvent.deleteField(String fieldId) = _DeleteField;
const factory RowDetailEvent.didReceiveCellDatas( const factory RowDetailEvent.didReceiveCellDatas(
List<GridCellIdentifier> gridCells) = _DidReceiveCellDatas; List<GridCellIdentifier> gridCells) = _DidReceiveCellDatas;
} }

View File

@ -317,9 +317,7 @@ class _GridFooter extends StatelessWidget {
height: GridSize.footerHeight, height: GridSize.footerHeight,
child: Padding( child: Padding(
padding: GridSize.footerContentInsets, padding: GridSize.footerContentInsets,
child: const Expanded( child: const SizedBox(height: 40, child: GridAddRowButton()),
child: SizedBox(height: 40, child: GridAddRowButton()),
),
), ),
), ),
), ),

View File

@ -2,6 +2,7 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option
import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_editor.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_editor.dart';
import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart';
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -215,9 +216,15 @@ extension _FieldActionExtension on FieldAction {
.add(const FieldActionSheetEvent.duplicateField()); .add(const FieldActionSheetEvent.duplicateField());
break; break;
case FieldAction.delete: case FieldAction.delete:
NavigatorAlertDialog(
title: LocaleKeys.grid_field_deleteFieldPromptMessage.tr(),
confirm: () {
context context
.read<FieldActionSheetBloc>() .read<FieldActionSheetBloc>()
.add(const FieldActionSheetEvent.deleteField()); .add(const FieldActionSheetEvent.deleteField());
},
).show(context);
break; break;
} }
} }

View File

@ -2,8 +2,13 @@ import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart'
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
import 'package:appflowy_popover/popover.dart'; import 'package:appflowy_popover/popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/log.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 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/generated/locale_keys.g.dart';
@ -13,14 +18,16 @@ import 'field_type_option_editor.dart';
class FieldEditor extends StatefulWidget { class FieldEditor extends StatefulWidget {
final String gridId; final String gridId;
final String fieldName; final String fieldName;
final VoidCallback? onRemoved; final bool isGroupField;
final Function(String)? onDeleted;
final IFieldTypeOptionLoader typeOptionLoader; final IFieldTypeOptionLoader typeOptionLoader;
const FieldEditor({ const FieldEditor({
required this.gridId, required this.gridId,
this.fieldName = "", this.fieldName = "",
required this.typeOptionLoader, required this.typeOptionLoader,
this.onRemoved, this.isGroupField = false,
this.onDeleted,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -43,10 +50,10 @@ class _FieldEditorState extends State<FieldEditor> {
create: (context) => FieldEditorBloc( create: (context) => FieldEditorBloc(
gridId: widget.gridId, gridId: widget.gridId,
fieldName: widget.fieldName, fieldName: widget.fieldName,
isGroupField: widget.isGroupField,
loader: widget.typeOptionLoader, loader: widget.typeOptionLoader,
)..add(const FieldEditorEvent.initial()), )..add(const FieldEditorEvent.initial()),
child: BlocBuilder<FieldEditorBloc, FieldEditorState>( child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
buildWhen: (p, c) => false,
builder: (context, state) { builder: (context, state) {
return ListView( return ListView(
shrinkWrap: true, shrinkWrap: true,
@ -56,6 +63,16 @@ class _FieldEditorState extends State<FieldEditor> {
const VSpace(10), const VSpace(10),
const _FieldNameCell(), const _FieldNameCell(),
const VSpace(10), const VSpace(10),
_DeleteFieldButton(
popoverMutex: popoverMutex,
onDeleted: () {
state.field.fold(
() => Log.error('Can not delete the field'),
(field) => widget.onDeleted?.call(field.id),
);
},
),
const VSpace(10),
_FieldTypeOptionCell(popoverMutex: popoverMutex), _FieldTypeOptionCell(popoverMutex: popoverMutex),
], ],
); );
@ -114,3 +131,55 @@ class _FieldNameCell extends StatelessWidget {
); );
} }
} }
class _DeleteFieldButton extends StatelessWidget {
final PopoverMutex popoverMutex;
final VoidCallback? onDeleted;
const _DeleteFieldButton({
required this.popoverMutex,
required this.onDeleted,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
buildWhen: (previous, current) => previous != current,
builder: (context, state) {
final enable = !state.canDelete && !state.isGroupField;
Widget button = FlowyButton(
text: FlowyText.medium(
LocaleKeys.grid_field_delete.tr(),
fontSize: 12,
color: enable ? null : theme.shader4,
),
);
if (enable) button = _wrapPopover(button);
return button;
},
);
}
Widget _wrapPopover(Widget widget) {
return AppFlowyStylePopover(
triggerActions: PopoverTriggerActionFlags.click,
constraints: BoxConstraints.loose(const Size(400, 240)),
mutex: popoverMutex,
direction: PopoverDirection.center,
popupBuilder: (popupContext) {
return PopoverAlertView(
title: LocaleKeys.grid_field_deleteFieldPromptMessage.tr(),
cancel: () => popoverMutex.state?.close(),
confirm: () {
onDeleted?.call();
popoverMutex.state?.close();
},
popoverMutex: popoverMutex,
);
},
child: widget,
);
}
}

View File

@ -66,8 +66,7 @@ class FieldTypeOptionEditor extends StatelessWidget {
height: GridSize.typeOptionItemHeight, height: GridSize.typeOptionItemHeight,
child: AppFlowyStylePopover( child: AppFlowyStylePopover(
constraints: BoxConstraints.loose(const Size(460, 440)), constraints: BoxConstraints.loose(const Size(460, 440)),
triggerActions: triggerActions: PopoverTriggerActionFlags.click,
PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click,
mutex: popoverMutex, mutex: popoverMutex,
offset: const Offset(20, 0), offset: const Offset(20, 0),
popupBuilder: (context) { popupBuilder: (context) {

View File

@ -187,7 +187,10 @@ class CreateFieldButton extends StatelessWidget {
), ),
hoverColor: theme.shader6, hoverColor: theme.shader6,
onTap: () {}, onTap: () {},
leftIcon: svgWidget("home/add"), leftIcon: svgWidget(
"home/add",
color: theme.iconColor,
),
), ),
popupBuilder: (BuildContext popover) { popupBuilder: (BuildContext popover) {
return FieldEditor( return FieldEditor(

View File

@ -54,9 +54,10 @@ Widget? makeTypeOptionWidget({
return builder.build(context); return builder.build(context);
} }
TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder( TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
{required TypeOptionDataController dataController, required TypeOptionDataController dataController,
required PopoverMutex popoverMutex}) { required PopoverMutex popoverMutex,
}) {
final gridId = dataController.gridId; final gridId = dataController.gridId;
final fieldType = dataController.field.fieldType; final fieldType = dataController.field.fieldType;

View File

@ -114,6 +114,7 @@ class NumberFormatList extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const _FilterTextField(), const _FilterTextField(),
const VSpace(10),
BlocBuilder<NumberFormatBloc, NumberFormatState>( BlocBuilder<NumberFormatBloc, NumberFormatState>(
builder: (context, state) { builder: (context, state) {
final cells = state.formats.map((format) { final cells = state.formats.map((format) {

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/plugins/grid/application/row/row_action_sheet_bloc.dart'; import 'package:app_flowy/plugins/grid/application/row/row_action_sheet_bloc.dart';
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
@ -150,9 +151,15 @@ extension _RowActionExtension on _RowAction {
.add(const RowActionSheetEvent.duplicateRow()); .add(const RowActionSheetEvent.duplicateRow());
break; break;
case _RowAction.delete: case _RowAction.delete:
NavigatorAlertDialog(
title: LocaleKeys.grid_field_deleteFieldPromptMessage.tr(),
confirm: () {
context context
.read<RowActionSheetBloc>() .read<RowActionSheetBloc>()
.add(const RowActionSheetEvent.deleteRow()); .add(const RowActionSheetEvent.deleteRow());
},
).show(context);
break; break;
} }
} }

View File

@ -133,6 +133,7 @@ class _PropertyList extends StatelessWidget {
), ),
), ),
), ),
const VSpace(10),
_CreateFieldButton( _CreateFieldButton(
viewId: viewId, viewId: viewId,
onClosed: () { onClosed: () {
@ -144,12 +145,18 @@ class _PropertyList extends StatelessWidget {
); );
}); });
}, },
onOpened: () { onOpened: (controller) {
return OverlayContainer( return OverlayContainer(
constraints: BoxConstraints.loose(const Size(240, 200)), constraints: BoxConstraints.loose(const Size(240, 200)),
child: FieldEditor( child: FieldEditor(
gridId: viewId, gridId: viewId,
typeOptionLoader: NewFieldTypeOptionLoader(gridId: viewId), typeOptionLoader: NewFieldTypeOptionLoader(gridId: viewId),
onDeleted: (fieldId) {
controller.close();
context
.read<RowDetailBloc>()
.add(RowDetailEvent.deleteField(fieldId));
},
), ),
); );
}, },
@ -163,9 +170,11 @@ class _PropertyList extends StatelessWidget {
class _CreateFieldButton extends StatelessWidget { class _CreateFieldButton extends StatelessWidget {
final String viewId; final String viewId;
final Widget Function() onOpened; final Widget Function(PopoverController) onOpened;
final VoidCallback onClosed; final VoidCallback onClosed;
const _CreateFieldButton({ final PopoverController popoverController = PopoverController();
_CreateFieldButton({
required this.viewId, required this.viewId,
required this.onOpened, required this.onOpened,
required this.onClosed, required this.onClosed,
@ -177,11 +186,13 @@ class _CreateFieldButton extends StatelessWidget {
final theme = context.read<AppTheme>(); final theme = context.read<AppTheme>();
return Popover( return Popover(
controller: popoverController,
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.topWithLeftAligned,
onClose: onClosed, onClose: onClosed,
child: SizedBox( child: Container(
height: 40, height: 40,
decoration: _makeBoxDecoration(context),
child: FlowyButton( child: FlowyButton(
text: FlowyText.medium( text: FlowyText.medium(
LocaleKeys.grid_field_newColumn.tr(), LocaleKeys.grid_field_newColumn.tr(),
@ -192,7 +203,16 @@ class _CreateFieldButton extends StatelessWidget {
leftIcon: svgWidget("home/add"), leftIcon: svgWidget("home/add"),
), ),
), ),
popupBuilder: (BuildContext context) => onOpened(), popupBuilder: (BuildContext context) => onOpened(popoverController),
);
}
BoxDecoration _makeBoxDecoration(BuildContext context) {
final theme = context.read<AppTheme>();
final borderSide = BorderSide(color: theme.shader6, width: 1.0);
return BoxDecoration(
color: theme.surface,
border: Border(top: borderSide),
); );
} }
} }
@ -241,16 +261,23 @@ class _RowDetailCellState extends State<_RowDetailCell> {
child: Popover( child: Popover(
controller: popover, controller: popover,
offset: const Offset(20, 0), offset: const Offset(20, 0),
popupBuilder: (context) { popupBuilder: (popoverContext) {
return OverlayContainer( return OverlayContainer(
constraints: BoxConstraints.loose(const Size(240, 200)), constraints: BoxConstraints.loose(const Size(240, 200)),
child: FieldEditor( child: FieldEditor(
gridId: widget.cellId.gridId, gridId: widget.cellId.gridId,
fieldName: widget.cellId.fieldContext.field.name, fieldName: widget.cellId.fieldContext.field.name,
isGroupField: widget.cellId.fieldContext.isGroupField,
typeOptionLoader: FieldTypeOptionLoader( typeOptionLoader: FieldTypeOptionLoader(
gridId: widget.cellId.gridId, gridId: widget.cellId.gridId,
field: widget.cellId.fieldContext.field, field: widget.cellId.fieldContext.field,
), ),
onDeleted: (fieldId) {
popover.close();
context
.read<RowDetailBloc>()
.add(RowDetailEvent.deleteField(fieldId));
},
), ),
); );
}, },

View File

@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
@ -15,9 +14,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
class GridGroupList extends StatelessWidget { class GridGroupList extends StatelessWidget {
final String viewId; final String viewId;
final GridFieldController fieldController; final GridFieldController fieldController;
final VoidCallback onDismissed;
const GridGroupList({ const GridGroupList({
required this.viewId, required this.viewId,
required this.fieldController, required this.fieldController,
required this.onDismissed,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -33,6 +34,7 @@ class GridGroupList extends StatelessWidget {
final cells = state.fieldContexts.map((fieldContext) { final cells = state.fieldContexts.map((fieldContext) {
Widget cell = _GridGroupCell( Widget cell = _GridGroupCell(
fieldContext: fieldContext, fieldContext: fieldContext,
onSelected: () => onDismissed(),
key: ValueKey(fieldContext.id), key: ValueKey(fieldContext.id),
); );
@ -56,29 +58,16 @@ class GridGroupList extends StatelessWidget {
), ),
); );
} }
void show(BuildContext context) {
FlowyOverlay.of(context).insertWithAnchor(
widget: OverlayContainer(
constraints: BoxConstraints.loose(const Size(260, 400)),
child: this,
),
identifier: identifier(),
anchorContext: context,
anchorDirection: AnchorDirection.bottomRight,
style: FlowyOverlayStyle(blur: false),
);
}
static String identifier() {
return (GridGroupList).toString();
}
} }
class _GridGroupCell extends StatelessWidget { class _GridGroupCell extends StatelessWidget {
final VoidCallback onSelected;
final GridFieldContext fieldContext; final GridFieldContext fieldContext;
const _GridGroupCell({required this.fieldContext, Key? key}) const _GridGroupCell({
: super(key: key); required this.fieldContext,
required this.onSelected,
Key? key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -97,8 +86,10 @@ class _GridGroupCell extends StatelessWidget {
child: FlowyButton( child: FlowyButton(
text: FlowyText.medium(fieldContext.name, fontSize: 12), text: FlowyText.medium(fieldContext.name, fontSize: 12),
hoverColor: theme.hover, hoverColor: theme.hover,
leftIcon: svgWidget(fieldContext.fieldType.iconName(), leftIcon: svgWidget(
color: theme.iconColor), fieldContext.fieldType.iconName(),
color: theme.iconColor,
),
rightIcon: rightIcon, rightIcon: rightIcon,
onTap: () { onTap: () {
context.read<GridGroupBloc>().add( context.read<GridGroupBloc>().add(
@ -107,7 +98,8 @@ class _GridGroupCell extends StatelessWidget {
fieldContext.fieldType, fieldContext.fieldType,
), ),
); );
FlowyOverlay.of(context).remove(GridGroupList.identifier()); onSelected();
// FlowyOverlay.of(context).remove(GridGroupList.identifier());
}, },
), ),
); );

View File

@ -53,14 +53,17 @@ class _SettingButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return Popover( return AppFlowyStylePopover(
constraints: BoxConstraints.loose(const Size(260, 400)),
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
offset: const Offset(0, 10), offset: const Offset(0, 10),
child: FlowyIconButton( child: FlowyIconButton(
width: 22, width: 22,
hoverColor: theme.hover, hoverColor: theme.hover,
icon: svgWidget("grid/setting/setting") icon: svgWidget(
.padding(horizontal: 3, vertical: 3), "grid/setting/setting",
color: theme.iconColor,
).padding(horizontal: 3, vertical: 3),
), ),
popupBuilder: (BuildContext context) { popupBuilder: (BuildContext context) {
return _GridSettingListPopover(settingContext: settingContext); return _GridSettingListPopover(settingContext: settingContext);
@ -85,25 +88,19 @@ class _GridSettingListPopoverState extends State<_GridSettingListPopover> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_action == GridSettingAction.properties) { if (_action == GridSettingAction.properties) {
return OverlayContainer( return GridPropertyList(
constraints: BoxConstraints.loose(const Size(260, 400)),
child: GridPropertyList(
gridId: widget.settingContext.gridId, gridId: widget.settingContext.gridId,
fieldController: widget.settingContext.fieldController, fieldController: widget.settingContext.fieldController,
),
); );
} }
return OverlayContainer( return GridSettingList(
constraints: BoxConstraints.loose(const Size(140, 400)),
child: GridSettingList(
settingContext: widget.settingContext, settingContext: widget.settingContext,
onAction: (action, settingContext) { onAction: (action, settingContext) {
setState(() { setState(() {
_action = action; _action = action;
}); });
}, },
),
); );
} }
} }

View File

@ -30,7 +30,7 @@ class NewAppButton extends StatelessWidget {
} }
Future<void> _showCreateAppDialog(BuildContext context) async { Future<void> _showCreateAppDialog(BuildContext context) async {
return TextFieldDialog( return NavigatorTextFieldDialog(
title: LocaleKeys.newPageText.tr(), title: LocaleKeys.newPageText.tr(),
value: "", value: "",
confirm: (newValue) { confirm: (newValue) {

View File

@ -126,7 +126,7 @@ class MenuAppHeader extends StatelessWidget {
action.fold(() {}, (action) { action.fold(() {}, (action) {
switch (action) { switch (action) {
case AppDisclosureAction.rename: case AppDisclosureAction.rename:
TextFieldDialog( NavigatorTextFieldDialog(
title: LocaleKeys.menuAppHeader_renameDialog.tr(), title: LocaleKeys.menuAppHeader_renameDialog.tr(),
value: context.read<AppBloc>().state.app.name, value: context.read<AppBloc>().state.app.name,
confirm: (newValue) { confirm: (newValue) {

View File

@ -109,7 +109,7 @@ class ViewSectionItem extends StatelessWidget {
action.foldRight({}, (action, previous) { action.foldRight({}, (action, previous) {
switch (action) { switch (action) {
case ViewDisclosureAction.rename: case ViewDisclosureAction.rename:
TextFieldDialog( NavigatorTextFieldDialog(
title: LocaleKeys.disclosureAction_rename.tr(), title: LocaleKeys.disclosureAction_rename.tr(),
value: context.read<ViewBloc>().state.view.name, value: context.read<ViewBloc>().state.view.name,
confirm: (newValue) { confirm: (newValue) {

View File

@ -1,3 +1,4 @@
import 'package:appflowy_popover/popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/text_style.dart'; import 'package:flowy_infra/text_style.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
@ -15,13 +16,13 @@ import 'package:textstyle_extensions/textstyle_extensions.dart';
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/generated/locale_keys.g.dart';
class TextFieldDialog extends StatefulWidget { class NavigatorTextFieldDialog extends StatefulWidget {
final String value; final String value;
final String title; final String title;
final void Function()? cancel; final void Function()? cancel;
final void Function(String) confirm; final void Function(String) confirm;
const TextFieldDialog({ const NavigatorTextFieldDialog({
required this.title, required this.title,
required this.value, required this.value,
required this.confirm, required this.confirm,
@ -30,10 +31,10 @@ class TextFieldDialog extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
State<TextFieldDialog> createState() => _CreateTextFieldDialog(); State<NavigatorTextFieldDialog> createState() => _CreateTextFieldDialog();
} }
class _CreateTextFieldDialog extends State<TextFieldDialog> { class _CreateTextFieldDialog extends State<NavigatorTextFieldDialog> {
String newValue = ""; String newValue = "";
@override @override
@ -56,7 +57,8 @@ class _CreateTextFieldDialog extends State<TextFieldDialog> {
FlowyFormTextInput( FlowyFormTextInput(
hintText: LocaleKeys.dialogCreatePageNameHint.tr(), hintText: LocaleKeys.dialogCreatePageNameHint.tr(),
initialValue: widget.value, initialValue: widget.value,
textStyle: const TextStyle(fontSize: 24, fontWeight: FontWeight.w400), textStyle:
const TextStyle(fontSize: 24, fontWeight: FontWeight.w400),
autoFocus: true, autoFocus: true,
onChanged: (text) { onChanged: (text) {
newValue = text; newValue = text;
@ -70,11 +72,13 @@ class _CreateTextFieldDialog extends State<TextFieldDialog> {
OkCancelButton( OkCancelButton(
onOkPressed: () { onOkPressed: () {
widget.confirm(newValue); widget.confirm(newValue);
Navigator.of(context).pop();
}, },
onCancelPressed: () { onCancelPressed: () {
if (widget.cancel != null) { if (widget.cancel != null) {
widget.cancel!(); widget.cancel!();
} }
Navigator.of(context).pop();
}, },
) )
], ],
@ -83,12 +87,14 @@ class _CreateTextFieldDialog extends State<TextFieldDialog> {
} }
} }
class FlowyAlertDialog extends StatefulWidget { class PopoverAlertView extends StatelessWidget {
final PopoverMutex popoverMutex;
final String title; final String title;
final void Function()? cancel; final void Function()? cancel;
final void Function()? confirm; final void Function()? confirm;
const FlowyAlertDialog({ const PopoverAlertView({
required this.popoverMutex,
required this.title, required this.title,
this.confirm, this.confirm,
this.cancel, this.cancel,
@ -96,10 +102,46 @@ class FlowyAlertDialog extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
State<FlowyAlertDialog> createState() => _CreateFlowyAlertDialog(); Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return StyledDialog(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
...[
FlowyText.medium(title, color: theme.shader4),
],
if (confirm != null) ...[
const VSpace(20),
OkCancelButton(
onOkPressed: confirm,
onCancelPressed: cancel,
)
]
],
),
);
}
} }
class _CreateFlowyAlertDialog extends State<FlowyAlertDialog> { class NavigatorAlertDialog extends StatefulWidget {
final String title;
final void Function()? cancel;
final void Function()? confirm;
const NavigatorAlertDialog({
required this.title,
this.confirm,
this.cancel,
Key? key,
}) : super(key: key);
@override
State<NavigatorAlertDialog> createState() => _CreateFlowyAlertDialog();
}
class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -118,10 +160,13 @@ class _CreateFlowyAlertDialog extends State<FlowyAlertDialog> {
], ],
if (widget.confirm != null) ...[ if (widget.confirm != null) ...[
const VSpace(20), const VSpace(20),
OkCancelButton( OkCancelButton(onOkPressed: () {
onOkPressed: widget.confirm!, widget.confirm?.call();
onCancelPressed: widget.confirm, Navigator.of(context).pop();
) }, onCancelPressed: () {
widget.cancel?.call();
Navigator.of(context).pop();
})
] ]
], ],
), ),
@ -129,7 +174,7 @@ class _CreateFlowyAlertDialog extends State<FlowyAlertDialog> {
} }
} }
class OkCancelDialog extends StatelessWidget { class NavigatorOkCancelDialog extends StatelessWidget {
final VoidCallback? onOkPressed; final VoidCallback? onOkPressed;
final VoidCallback? onCancelPressed; final VoidCallback? onCancelPressed;
final String? okTitle; final String? okTitle;
@ -138,7 +183,7 @@ class OkCancelDialog extends StatelessWidget {
final String message; final String message;
final double? maxWidth; final double? maxWidth;
const OkCancelDialog( const NavigatorOkCancelDialog(
{Key? key, {Key? key,
this.onOkPressed, this.onOkPressed,
this.onCancelPressed, this.onCancelPressed,
@ -158,7 +203,7 @@ class OkCancelDialog extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
if (title != null) ...[ if (title != null) ...[
Text(title!.toUpperCase(), style: TextStyles.T1.textColor(theme.shader1)), FlowyText.medium(title!.toUpperCase(), color: theme.shader1),
VSpace(Insets.sm * 1.5), VSpace(Insets.sm * 1.5),
Container(color: theme.bg1, height: 1), Container(color: theme.bg1, height: 1),
VSpace(Insets.m * 1.5), VSpace(Insets.m * 1.5),
@ -166,8 +211,14 @@ class OkCancelDialog extends StatelessWidget {
Text(message, style: TextStyles.Body1.textHeight(1.5)), Text(message, style: TextStyles.Body1.textHeight(1.5)),
SizedBox(height: Insets.l), SizedBox(height: Insets.l),
OkCancelButton( OkCancelButton(
onOkPressed: onOkPressed, onOkPressed: () {
onCancelPressed: onCancelPressed, onOkPressed?.call();
Navigator.of(context).pop();
},
onCancelPressed: () {
onCancelPressed?.call();
Navigator.of(context).pop();
},
okTitle: okTitle?.toUpperCase(), okTitle: okTitle?.toUpperCase(),
cancelTitle: cancelTitle?.toUpperCase(), cancelTitle: cancelTitle?.toUpperCase(),
) )
@ -185,7 +236,12 @@ class OkCancelButton extends StatelessWidget {
final double? minHeight; final double? minHeight;
const OkCancelButton( const OkCancelButton(
{Key? key, this.onOkPressed, this.onCancelPressed, this.okTitle, this.cancelTitle, this.minHeight}) {Key? key,
this.onOkPressed,
this.onCancelPressed,
this.okTitle,
this.cancelTitle,
this.minHeight})
: super(key: key); : super(key: key);
@override @override
@ -198,20 +254,14 @@ class OkCancelButton extends StatelessWidget {
if (onCancelPressed != null) if (onCancelPressed != null)
SecondaryTextButton( SecondaryTextButton(
cancelTitle ?? LocaleKeys.button_Cancel.tr(), cancelTitle ?? LocaleKeys.button_Cancel.tr(),
onPressed: () { onPressed: onCancelPressed,
onCancelPressed!();
AppGlobals.nav.pop();
},
bigMode: true, bigMode: true,
), ),
HSpace(Insets.m), HSpace(Insets.m),
if (onOkPressed != null) if (onOkPressed != null)
PrimaryTextButton( PrimaryTextButton(
okTitle ?? LocaleKeys.button_OK.tr(), okTitle ?? LocaleKeys.button_OK.tr(),
onPressed: () { onPressed: onOkPressed,
onOkPressed!();
AppGlobals.nav.pop();
},
bigMode: true, bigMode: true,
), ),
], ],

View File

@ -416,6 +416,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = { buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
@ -549,6 +550,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = { buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
@ -573,6 +575,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = { buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;

View File

@ -59,7 +59,7 @@ class Popover extends StatefulWidget {
final Decoration? maskDecoration; final Decoration? maskDecoration;
/// The function used to build the popover. /// The function used to build the popover.
final Widget Function(BuildContext context) popupBuilder; final Widget? Function(BuildContext context) popupBuilder;
final int triggerActions; final int triggerActions;
@ -265,7 +265,7 @@ class _PopoverMaskState extends State<_PopoverMask> {
} }
class PopoverContainer extends StatefulWidget { class PopoverContainer extends StatefulWidget {
final Widget Function(BuildContext context) popupBuilder; final Widget? Function(BuildContext context) popupBuilder;
final PopoverDirection direction; final PopoverDirection direction;
final PopoverLink popoverLink; final PopoverLink popoverLink;
final Offset offset; final Offset offset;

View File

@ -35,6 +35,8 @@ class AppFlowyStylePopover extends StatelessWidget {
mutex: mutex, mutex: mutex,
triggerActions: triggerActions, triggerActions: triggerActions,
popupBuilder: (context) { popupBuilder: (context) {
final child = popupBuilder(context);
debugPrint('$child popover');
return OverlayContainer( return OverlayContainer(
constraints: constraints, constraints: constraints,
child: popupBuilder(context), child: popupBuilder(context),

View File

@ -1,22 +1,30 @@
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/text_style.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'base_styled_button.dart'; import 'base_styled_button.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
class PrimaryTextButton extends StatelessWidget { class PrimaryTextButton extends StatelessWidget {
final String label; final String label;
final VoidCallback? onPressed; final VoidCallback? onPressed;
final bool bigMode; final bool bigMode;
const PrimaryTextButton(this.label, {Key? key, this.onPressed, this.bigMode = false}) : super(key: key); const PrimaryTextButton(this.label,
{Key? key, this.onPressed, this.bigMode = false})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
TextStyle txtStyle = TextStyles.Btn.textColor(Colors.white); final theme = context.watch<AppTheme>();
return PrimaryButton(bigMode: bigMode, onPressed: onPressed, child: Text(label, style: txtStyle)); return PrimaryButton(
bigMode: bigMode,
onPressed: onPressed,
child: FlowyText.regular(
label,
color: theme.surface,
),
);
} }
} }
@ -25,14 +33,16 @@ class PrimaryButton extends StatelessWidget {
final VoidCallback? onPressed; final VoidCallback? onPressed;
final bool bigMode; final bool bigMode;
const PrimaryButton({Key? key, required this.child, this.onPressed, this.bigMode = false}) : super(key: key); const PrimaryButton(
{Key? key, required this.child, this.onPressed, this.bigMode = false})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return BaseStyledButton( return BaseStyledButton(
minWidth: bigMode ? 170 : 78, minWidth: bigMode ? 100 : 80,
minHeight: bigMode ? 48 : 28, minHeight: bigMode ? 40 : 38,
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
bgColor: theme.main1, bgColor: theme.main1,
hoverColor: theme.main1, hoverColor: theme.main1,

View File

@ -1,9 +1,8 @@
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
// ignore: import_of_legacy_library_into_null_safe // ignore: import_of_legacy_library_into_null_safe
import 'package:textstyle_extensions/textstyle_extensions.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/text_style.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'base_styled_button.dart'; import 'base_styled_button.dart';
@ -12,13 +11,21 @@ class SecondaryTextButton extends StatelessWidget {
final VoidCallback? onPressed; final VoidCallback? onPressed;
final bool bigMode; final bool bigMode;
const SecondaryTextButton(this.label, {Key? key, this.onPressed, this.bigMode = false}) : super(key: key); const SecondaryTextButton(this.label,
{Key? key, this.onPressed, this.bigMode = false})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
TextStyle txtStyle = TextStyles.Btn.textColor(theme.main1); return SecondaryButton(
return SecondaryButton(bigMode: bigMode, onPressed: onPressed, child: Text(label, style: txtStyle)); bigMode: bigMode,
onPressed: onPressed,
child: FlowyText.regular(
label,
color: theme.main1,
),
);
} }
} }
@ -27,14 +34,16 @@ class SecondaryButton extends StatelessWidget {
final VoidCallback? onPressed; final VoidCallback? onPressed;
final bool bigMode; final bool bigMode;
const SecondaryButton({Key? key, required this.child, this.onPressed, this.bigMode = false}) : super(key: key); const SecondaryButton(
{Key? key, required this.child, this.onPressed, this.bigMode = false})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return BaseStyledButton( return BaseStyledButton(
minWidth: bigMode ? 170 : 78, minWidth: bigMode ? 100 : 80,
minHeight: bigMode ? 48 : 28, minHeight: bigMode ? 40 : 38,
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
bgColor: theme.shader7, bgColor: theme.shader7,
hoverColor: theme.hover, hoverColor: theme.hover,

View File

@ -1,3 +1,3 @@
class DialogSize { class DialogSize {
static double get minDialogWidth => 480; static double get minDialogWidth => 400;
} }

View File

@ -65,7 +65,7 @@ class StyledDialog extends StatelessWidget {
return FocusTraversalGroup( return FocusTraversalGroup(
child: Container( child: Container(
margin: margin ?? EdgeInsets.all(Insets.lGutter * 2), margin: margin ?? EdgeInsets.all(Insets.sm * 2),
alignment: Alignment.center, alignment: Alignment.center,
child: Container( child: Container(
constraints: BoxConstraints( constraints: BoxConstraints(
@ -133,7 +133,9 @@ class StyledDialogRoute<T> extends PopupRoute<T> {
super(settings: settings, filter: barrier.filter); super(settings: settings, filter: barrier.filter);
@override @override
bool get barrierDismissible => barrier.dismissible; bool get barrierDismissible {
return barrier.dismissible;
}
@override @override
String get barrierLabel => barrier.label; String get barrierLabel => barrier.label;