chore: inkwell mobile quick action sheets (#4576)

* chore: inkwell mobile quick action sheets

* chore: more subtle tap effect

* chore: improve code style
This commit is contained in:
Richard Shiue 2024-02-04 00:55:05 +08:00 committed by GitHub
parent 5cbc8b1e18
commit 8c1d0106dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 107 additions and 119 deletions

View File

@ -1,7 +1,8 @@
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/widgets/widgets.dart'; import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_quick_action_button.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/widget/separated_flex.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
enum MobileViewItemBottomSheetBodyAction { enum MobileViewItemBottomSheetBodyAction {
@ -25,55 +26,46 @@ class MobileViewItemBottomSheetBody extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return SeparatedColumn(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
separatorBuilder: () => const Divider(
height: 8.5,
thickness: 0.5,
),
children: [ children: [
FlowyOptionTile.text( MobileQuickActionButton(
text: LocaleKeys.button_rename.tr(), text: LocaleKeys.button_rename.tr(),
leftIcon: const FlowySvg( icon: FlowySvgs.m_rename_s,
FlowySvgs.m_rename_s,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
MobileViewItemBottomSheetBodyAction.rename, MobileViewItemBottomSheetBodyAction.rename,
), ),
), ),
FlowyOptionTile.text( MobileQuickActionButton(
text: isFavorite text: isFavorite
? LocaleKeys.button_removeFromFavorites.tr() ? LocaleKeys.button_removeFromFavorites.tr()
: LocaleKeys.button_addToFavorites.tr(), : LocaleKeys.button_addToFavorites.tr(),
leftIcon: FlowySvg( icon: isFavorite
size: const Size(20, 20), ? FlowySvgs.m_favorite_selected_lg
isFavorite : FlowySvgs.m_favorite_unselected_lg,
? FlowySvgs.m_favorite_selected_lg iconColor: isFavorite ? Colors.yellow : null,
: FlowySvgs.m_favorite_unselected_lg,
color: isFavorite ? Colors.yellow : null,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
isFavorite isFavorite
? MobileViewItemBottomSheetBodyAction.removeFromFavorites ? MobileViewItemBottomSheetBodyAction.removeFromFavorites
: MobileViewItemBottomSheetBodyAction.addToFavorites, : MobileViewItemBottomSheetBodyAction.addToFavorites,
), ),
), ),
FlowyOptionTile.text( MobileQuickActionButton(
text: LocaleKeys.button_duplicate.tr(), text: LocaleKeys.button_duplicate.tr(),
leftIcon: const FlowySvg( icon: FlowySvgs.m_duplicate_s,
FlowySvgs.m_duplicate_s,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
MobileViewItemBottomSheetBodyAction.duplicate, MobileViewItemBottomSheetBodyAction.duplicate,
), ),
), ),
FlowyOptionTile.text( MobileQuickActionButton(
text: LocaleKeys.button_delete.tr(), text: LocaleKeys.button_delete.tr(),
textColor: Theme.of(context).colorScheme.error, textColor: Theme.of(context).colorScheme.error,
leftIcon: FlowySvg( icon: FlowySvgs.m_delete_s,
FlowySvgs.m_delete_s, iconColor: Theme.of(context).colorScheme.error,
color: Theme.of(context).colorScheme.error,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
MobileViewItemBottomSheetBodyAction.delete, MobileViewItemBottomSheetBodyAction.delete,
), ),

View File

@ -1,9 +1,10 @@
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart'; import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/widgets/widgets.dart'; import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_quick_action_button.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
enum MobileViewBottomSheetBodyAction { enum MobileViewBottomSheetBodyAction {
@ -84,55 +85,46 @@ class MobileViewBottomSheetBody extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isFavorite = view.isFavorite; final isFavorite = view.isFavorite;
return Column( return SeparatedColumn(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
separatorBuilder: () => const Divider(
height: 8.5,
thickness: 0.5,
),
children: [ children: [
FlowyOptionTile.text( MobileQuickActionButton(
text: LocaleKeys.button_rename.tr(), text: LocaleKeys.button_rename.tr(),
leftIcon: const FlowySvg( icon: FlowySvgs.m_rename_s,
FlowySvgs.m_rename_s,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
MobileViewBottomSheetBodyAction.rename, MobileViewBottomSheetBodyAction.rename,
), ),
), ),
FlowyOptionTile.text( MobileQuickActionButton(
text: isFavorite text: isFavorite
? LocaleKeys.button_removeFromFavorites.tr() ? LocaleKeys.button_removeFromFavorites.tr()
: LocaleKeys.button_addToFavorites.tr(), : LocaleKeys.button_addToFavorites.tr(),
leftIcon: FlowySvg( icon: isFavorite
size: const Size(20, 20), ? FlowySvgs.m_favorite_selected_lg
isFavorite : FlowySvgs.m_favorite_unselected_lg,
? FlowySvgs.m_favorite_selected_lg iconColor: isFavorite ? Colors.yellow : null,
: FlowySvgs.m_favorite_unselected_lg,
color: isFavorite ? Colors.yellow : null,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
isFavorite isFavorite
? MobileViewBottomSheetBodyAction.removeFromFavorites ? MobileViewBottomSheetBodyAction.removeFromFavorites
: MobileViewBottomSheetBodyAction.addToFavorites, : MobileViewBottomSheetBodyAction.addToFavorites,
), ),
), ),
FlowyOptionTile.text( MobileQuickActionButton(
text: LocaleKeys.button_duplicate.tr(), text: LocaleKeys.button_duplicate.tr(),
leftIcon: const FlowySvg( icon: FlowySvgs.m_duplicate_s,
FlowySvgs.m_duplicate_s,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
MobileViewBottomSheetBodyAction.duplicate, MobileViewBottomSheetBodyAction.duplicate,
), ),
), ),
FlowyOptionTile.text( MobileQuickActionButton(
text: LocaleKeys.button_delete.tr(), text: LocaleKeys.button_delete.tr(),
textColor: Theme.of(context).colorScheme.error, textColor: Theme.of(context).colorScheme.error,
leftIcon: FlowySvg( icon: FlowySvgs.m_delete_s,
FlowySvgs.m_delete_s, iconColor: Theme.of(context).colorScheme.error,
color: Theme.of(context).colorScheme.error,
),
showTopBorder: false,
onTap: () => onAction( onTap: () => onAction(
MobileViewBottomSheetBodyAction.delete, MobileViewBottomSheetBodyAction.delete,
), ),

View File

@ -135,54 +135,44 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
builder: (_) => Column( builder: (_) => Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Padding( MobileQuickActionButton(
padding: const EdgeInsets.symmetric(horizontal: 8.0), onTap: () =>
child: MobileQuickActionButton( _performAction(viewId, _bloc.state.currentRowId, false),
onTap: () { icon: FlowySvgs.copy_s,
final rowId = _bloc.state.currentRowId; text: LocaleKeys.button_duplicate.tr(),
if (rowId == null) {
return;
}
RowBackendService.duplicateRow(viewId, rowId);
context
..pop()
..pop();
Fluttertoast.showToast(
msg: LocaleKeys.board_cardDuplicated.tr(),
gravity: ToastGravity.BOTTOM,
);
},
icon: FlowySvgs.copy_s,
text: LocaleKeys.button_duplicate.tr(),
),
), ),
const Divider(height: 9), const Divider(height: 8.5, thickness: 0.5),
Padding( MobileQuickActionButton(
padding: const EdgeInsets.symmetric(horizontal: 8.0), onTap: () => _performAction(viewId, _bloc.state.currentRowId, true),
child: MobileQuickActionButton( text: LocaleKeys.button_delete.tr(),
onTap: () { textColor: Theme.of(context).colorScheme.error,
final rowId = _bloc.state.currentRowId; icon: FlowySvgs.m_delete_m,
if (rowId == null) { iconColor: Theme.of(context).colorScheme.error,
return;
}
RowBackendService.deleteRow(viewId, rowId);
context
..pop()
..pop();
Fluttertoast.showToast(
msg: LocaleKeys.board_cardDeleted.tr(),
gravity: ToastGravity.BOTTOM,
);
},
icon: FlowySvgs.m_delete_m,
text: LocaleKeys.button_delete.tr(),
color: Theme.of(context).colorScheme.error,
),
), ),
], ],
), ),
); );
} }
void _performAction(String viewId, String? rowId, bool deleteRow) {
if (rowId == null) {
return;
}
deleteRow
? RowBackendService.deleteRow(viewId, rowId)
: RowBackendService.duplicateRow(viewId, rowId);
context
..pop()
..pop();
Fluttertoast.showToast(
msg: deleteRow
? LocaleKeys.board_cardDeleted.tr()
: LocaleKeys.board_cardDuplicated.tr(),
gravity: ToastGravity.BOTTOM,
);
}
} }
class RowDetailFab extends StatelessWidget { class RowDetailFab extends StatelessWidget {

View File

@ -72,18 +72,16 @@ class MobileDatabaseViewQuickActions extends StatelessWidget {
_Action action, _Action action,
VoidCallback onTap, VoidCallback onTap,
) { ) {
return Padding( return MobileQuickActionButton(
padding: const EdgeInsets.symmetric(horizontal: 8.0), icon: action.icon,
child: MobileQuickActionButton( text: action.label,
icon: action.icon, textColor: action.color(context),
text: action.label, iconColor: action.color(context),
color: action.color(context), onTap: onTap,
onTap: onTap,
),
); );
} }
Widget _divider() => const Divider(height: 9); Widget _divider() => const Divider(height: 8.5, thickness: 0.5);
} }
enum _Action { enum _Action {

View File

@ -8,28 +8,44 @@ class MobileQuickActionButton extends StatelessWidget {
required this.onTap, required this.onTap,
required this.icon, required this.icon,
required this.text, required this.text,
this.color, this.textColor,
this.iconColor,
}); });
final VoidCallback onTap; final VoidCallback onTap;
final FlowySvgData icon; final FlowySvgData icon;
final String text; final String text;
final Color? color; final Color? textColor;
final Color? iconColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return Padding(
onTap: onTap, padding: const EdgeInsets.symmetric(horizontal: 4),
borderRadius: BorderRadius.circular(12), child: InkWell(
child: Container( onTap: onTap,
height: 44, borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.symmetric(horizontal: 8), splashColor: Colors.transparent,
child: Row( child: Container(
children: [ height: 44,
FlowySvg(icon, size: const Size.square(20), color: color), padding: const EdgeInsets.symmetric(horizontal: 12),
const HSpace(8), child: Row(
FlowyText(text, fontSize: 15, color: color), children: [
], FlowySvg(
icon,
size: const Size.square(20),
color: iconColor,
),
const HSpace(12),
Expanded(
child: FlowyText(
text,
fontSize: 15,
color: textColor,
),
),
],
),
), ),
), ),
); );