mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-11-04 03:54:44 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									5cbc8b1e18
								
							
						
					
					
						commit
						8c1d0106dd
					
				@ -1,7 +1,8 @@
 | 
			
		||||
import 'package:appflowy/generated/flowy_svgs.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:flowy_infra_ui/widget/separated_flex.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
enum MobileViewItemBottomSheetBodyAction {
 | 
			
		||||
@ -25,55 +26,46 @@ class MobileViewItemBottomSheetBody extends StatelessWidget {
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Column(
 | 
			
		||||
    return SeparatedColumn(
 | 
			
		||||
      crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
			
		||||
      separatorBuilder: () => const Divider(
 | 
			
		||||
        height: 8.5,
 | 
			
		||||
        thickness: 0.5,
 | 
			
		||||
      ),
 | 
			
		||||
      children: [
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: LocaleKeys.button_rename.tr(),
 | 
			
		||||
          leftIcon: const FlowySvg(
 | 
			
		||||
            FlowySvgs.m_rename_s,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: FlowySvgs.m_rename_s,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            MobileViewItemBottomSheetBodyAction.rename,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: isFavorite
 | 
			
		||||
              ? LocaleKeys.button_removeFromFavorites.tr()
 | 
			
		||||
              : LocaleKeys.button_addToFavorites.tr(),
 | 
			
		||||
          leftIcon: FlowySvg(
 | 
			
		||||
            size: const Size(20, 20),
 | 
			
		||||
            isFavorite
 | 
			
		||||
                ? FlowySvgs.m_favorite_selected_lg
 | 
			
		||||
                : FlowySvgs.m_favorite_unselected_lg,
 | 
			
		||||
            color: isFavorite ? Colors.yellow : null,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: isFavorite
 | 
			
		||||
              ? FlowySvgs.m_favorite_selected_lg
 | 
			
		||||
              : FlowySvgs.m_favorite_unselected_lg,
 | 
			
		||||
          iconColor: isFavorite ? Colors.yellow : null,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            isFavorite
 | 
			
		||||
                ? MobileViewItemBottomSheetBodyAction.removeFromFavorites
 | 
			
		||||
                : MobileViewItemBottomSheetBodyAction.addToFavorites,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: LocaleKeys.button_duplicate.tr(),
 | 
			
		||||
          leftIcon: const FlowySvg(
 | 
			
		||||
            FlowySvgs.m_duplicate_s,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: FlowySvgs.m_duplicate_s,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            MobileViewItemBottomSheetBodyAction.duplicate,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: LocaleKeys.button_delete.tr(),
 | 
			
		||||
          textColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
          leftIcon: FlowySvg(
 | 
			
		||||
            FlowySvgs.m_delete_s,
 | 
			
		||||
            color: Theme.of(context).colorScheme.error,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: FlowySvgs.m_delete_s,
 | 
			
		||||
          iconColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            MobileViewItemBottomSheetBodyAction.delete,
 | 
			
		||||
          ),
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,10 @@
 | 
			
		||||
import 'package:appflowy/generated/flowy_svgs.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/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:easy_localization/easy_localization.dart';
 | 
			
		||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
enum MobileViewBottomSheetBodyAction {
 | 
			
		||||
@ -84,55 +85,46 @@ class MobileViewBottomSheetBody extends StatelessWidget {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final isFavorite = view.isFavorite;
 | 
			
		||||
    return Column(
 | 
			
		||||
    return SeparatedColumn(
 | 
			
		||||
      crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
			
		||||
      separatorBuilder: () => const Divider(
 | 
			
		||||
        height: 8.5,
 | 
			
		||||
        thickness: 0.5,
 | 
			
		||||
      ),
 | 
			
		||||
      children: [
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: LocaleKeys.button_rename.tr(),
 | 
			
		||||
          leftIcon: const FlowySvg(
 | 
			
		||||
            FlowySvgs.m_rename_s,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: FlowySvgs.m_rename_s,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            MobileViewBottomSheetBodyAction.rename,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: isFavorite
 | 
			
		||||
              ? LocaleKeys.button_removeFromFavorites.tr()
 | 
			
		||||
              : LocaleKeys.button_addToFavorites.tr(),
 | 
			
		||||
          leftIcon: FlowySvg(
 | 
			
		||||
            size: const Size(20, 20),
 | 
			
		||||
            isFavorite
 | 
			
		||||
                ? FlowySvgs.m_favorite_selected_lg
 | 
			
		||||
                : FlowySvgs.m_favorite_unselected_lg,
 | 
			
		||||
            color: isFavorite ? Colors.yellow : null,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: isFavorite
 | 
			
		||||
              ? FlowySvgs.m_favorite_selected_lg
 | 
			
		||||
              : FlowySvgs.m_favorite_unselected_lg,
 | 
			
		||||
          iconColor: isFavorite ? Colors.yellow : null,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            isFavorite
 | 
			
		||||
                ? MobileViewBottomSheetBodyAction.removeFromFavorites
 | 
			
		||||
                : MobileViewBottomSheetBodyAction.addToFavorites,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: LocaleKeys.button_duplicate.tr(),
 | 
			
		||||
          leftIcon: const FlowySvg(
 | 
			
		||||
            FlowySvgs.m_duplicate_s,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: FlowySvgs.m_duplicate_s,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            MobileViewBottomSheetBodyAction.duplicate,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        FlowyOptionTile.text(
 | 
			
		||||
        MobileQuickActionButton(
 | 
			
		||||
          text: LocaleKeys.button_delete.tr(),
 | 
			
		||||
          textColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
          leftIcon: FlowySvg(
 | 
			
		||||
            FlowySvgs.m_delete_s,
 | 
			
		||||
            color: Theme.of(context).colorScheme.error,
 | 
			
		||||
          ),
 | 
			
		||||
          showTopBorder: false,
 | 
			
		||||
          icon: FlowySvgs.m_delete_s,
 | 
			
		||||
          iconColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
          onTap: () => onAction(
 | 
			
		||||
            MobileViewBottomSheetBodyAction.delete,
 | 
			
		||||
          ),
 | 
			
		||||
 | 
			
		||||
@ -135,54 +135,44 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
 | 
			
		||||
      builder: (_) => Column(
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        children: [
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.symmetric(horizontal: 8.0),
 | 
			
		||||
            child: MobileQuickActionButton(
 | 
			
		||||
              onTap: () {
 | 
			
		||||
                final rowId = _bloc.state.currentRowId;
 | 
			
		||||
                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(),
 | 
			
		||||
            ),
 | 
			
		||||
          MobileQuickActionButton(
 | 
			
		||||
            onTap: () =>
 | 
			
		||||
                _performAction(viewId, _bloc.state.currentRowId, false),
 | 
			
		||||
            icon: FlowySvgs.copy_s,
 | 
			
		||||
            text: LocaleKeys.button_duplicate.tr(),
 | 
			
		||||
          ),
 | 
			
		||||
          const Divider(height: 9),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.symmetric(horizontal: 8.0),
 | 
			
		||||
            child: MobileQuickActionButton(
 | 
			
		||||
              onTap: () {
 | 
			
		||||
                final rowId = _bloc.state.currentRowId;
 | 
			
		||||
                if (rowId == null) {
 | 
			
		||||
                  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,
 | 
			
		||||
            ),
 | 
			
		||||
          const Divider(height: 8.5, thickness: 0.5),
 | 
			
		||||
          MobileQuickActionButton(
 | 
			
		||||
            onTap: () => _performAction(viewId, _bloc.state.currentRowId, true),
 | 
			
		||||
            text: LocaleKeys.button_delete.tr(),
 | 
			
		||||
            textColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
            icon: FlowySvgs.m_delete_m,
 | 
			
		||||
            iconColor: 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 {
 | 
			
		||||
 | 
			
		||||
@ -72,18 +72,16 @@ class MobileDatabaseViewQuickActions extends StatelessWidget {
 | 
			
		||||
    _Action action,
 | 
			
		||||
    VoidCallback onTap,
 | 
			
		||||
  ) {
 | 
			
		||||
    return Padding(
 | 
			
		||||
      padding: const EdgeInsets.symmetric(horizontal: 8.0),
 | 
			
		||||
      child: MobileQuickActionButton(
 | 
			
		||||
        icon: action.icon,
 | 
			
		||||
        text: action.label,
 | 
			
		||||
        color: action.color(context),
 | 
			
		||||
        onTap: onTap,
 | 
			
		||||
      ),
 | 
			
		||||
    return MobileQuickActionButton(
 | 
			
		||||
      icon: action.icon,
 | 
			
		||||
      text: action.label,
 | 
			
		||||
      textColor: action.color(context),
 | 
			
		||||
      iconColor: action.color(context),
 | 
			
		||||
      onTap: onTap,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Widget _divider() => const Divider(height: 9);
 | 
			
		||||
  Widget _divider() => const Divider(height: 8.5, thickness: 0.5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum _Action {
 | 
			
		||||
 | 
			
		||||
@ -8,28 +8,44 @@ class MobileQuickActionButton extends StatelessWidget {
 | 
			
		||||
    required this.onTap,
 | 
			
		||||
    required this.icon,
 | 
			
		||||
    required this.text,
 | 
			
		||||
    this.color,
 | 
			
		||||
    this.textColor,
 | 
			
		||||
    this.iconColor,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  final VoidCallback onTap;
 | 
			
		||||
  final FlowySvgData icon;
 | 
			
		||||
  final String text;
 | 
			
		||||
  final Color? color;
 | 
			
		||||
  final Color? textColor;
 | 
			
		||||
  final Color? iconColor;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return InkWell(
 | 
			
		||||
      onTap: onTap,
 | 
			
		||||
      borderRadius: BorderRadius.circular(12),
 | 
			
		||||
      child: Container(
 | 
			
		||||
        height: 44,
 | 
			
		||||
        padding: const EdgeInsets.symmetric(horizontal: 8),
 | 
			
		||||
        child: Row(
 | 
			
		||||
          children: [
 | 
			
		||||
            FlowySvg(icon, size: const Size.square(20), color: color),
 | 
			
		||||
            const HSpace(8),
 | 
			
		||||
            FlowyText(text, fontSize: 15, color: color),
 | 
			
		||||
          ],
 | 
			
		||||
    return Padding(
 | 
			
		||||
      padding: const EdgeInsets.symmetric(horizontal: 4),
 | 
			
		||||
      child: InkWell(
 | 
			
		||||
        onTap: onTap,
 | 
			
		||||
        borderRadius: BorderRadius.circular(12),
 | 
			
		||||
        splashColor: Colors.transparent,
 | 
			
		||||
        child: Container(
 | 
			
		||||
          height: 44,
 | 
			
		||||
          padding: const EdgeInsets.symmetric(horizontal: 12),
 | 
			
		||||
          child: Row(
 | 
			
		||||
            children: [
 | 
			
		||||
              FlowySvg(
 | 
			
		||||
                icon,
 | 
			
		||||
                size: const Size.square(20),
 | 
			
		||||
                color: iconColor,
 | 
			
		||||
              ),
 | 
			
		||||
              const HSpace(12),
 | 
			
		||||
              Expanded(
 | 
			
		||||
                child: FlowyText(
 | 
			
		||||
                  text,
 | 
			
		||||
                  fontSize: 15,
 | 
			
		||||
                  color: textColor,
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user