Skip to content

[iOS, Android] The 'Cut' context menu button won't appear in text fields when toolbarOptions are passed #119820

@ksokolovskyi

Description

@ksokolovskyi

Steps to Reproduce

  1. Execute flutter run on the code sample;
  2. Type text on any of the fields;
  3. Select typed text;
  4. You will see the Select All, Copy, and Paste buttons. On the Select All button's place should be Cut, because the selectAll property is set to false in the provided ToolbarOptions;
  5. Comment toolbarOptions of that field and the Cut button will be available.

Actual results

toolbar_options_ko.mov

Expected results

toolbar_options_ok.mov

The toolbarOptions were deprecated after v3.3.0-0.5.pre, but many users can still use them and be affected by this bug.
This bug is reproducible in stable (v3.7.0) and master (3.7.0-30.0.pre).

Fix

The root of this issue is located in the flutter/lib/src/widgets/editable_text.dart in the method buttonItemsForToolbarOptions

List<ContextMenuButtonItem>? buttonItemsForToolbarOptions([TargetPlatform? targetPlatform]) {
    final ToolbarOptions toolbarOptions = widget.toolbarOptions;
    if (toolbarOptions == ToolbarOptions.empty) {
      return null;
    }
    return <ContextMenuButtonItem>[
      if (toolbarOptions.cut && cutEnabled)
        ContextMenuButtonItem(
          onPressed: () {
            selectAll(SelectionChangedCause.toolbar);
          },
          type: ContextMenuButtonType.selectAll,
        ),
      if (toolbarOptions.copy && copyEnabled)
        ContextMenuButtonItem(
          onPressed: () {
            copySelection(SelectionChangedCause.toolbar);
          },
          type: ContextMenuButtonType.copy,
        ),
      if (toolbarOptions.paste && clipboardStatus != null && pasteEnabled)
        ContextMenuButtonItem(
          onPressed: () {
            pasteText(SelectionChangedCause.toolbar);
          },
          type: ContextMenuButtonType.paste,
        ),
      if (toolbarOptions.selectAll && selectAllEnabled)
        ContextMenuButtonItem(
          onPressed: () {
            selectAll(SelectionChangedCause.toolbar);
          },
          type: ContextMenuButtonType.selectAll,
        ),
    ];
  }

As you can see we have wrong ContextMenuButtonItem insertion after the if (toolbarOptions.cut && cutEnabled) condition.
It seems to be a copy-paste from the if (toolbarOptions.selectAll && selectAllEnabled) condition.

Code sample

main.dart

// ignore_for_file: deprecated_member_use

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Flutter Demo',
    theme: ThemeData(
      primarySwatch: Colors.blue,
      useMaterial3: false,
    ),
    home: Scaffold(
      backgroundColor: Colors.grey[100],
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('TextField'),
              const TextField(
                toolbarOptions: ToolbarOptions(
                  cut: true,
                  copy: true,
                  paste: true,
                  selectAll: false,
                ),
              ),
              const SizedBox(height: 15),
              const Text('TextFormField'),
              TextFormField(
                toolbarOptions: const ToolbarOptions(
                  cut: true,
                  copy: true,
                  paste: true,
                  selectAll: false,
                ),
              ),
              const SizedBox(height: 15),
              const Text('CupertinoTextField'),
              const CupertinoTextField(
                toolbarOptions: ToolbarOptions(
                  cut: true,
                  copy: true,
                  paste: true,
                  selectAll: false,
                ),
              ),
              const SizedBox(height: 15),
              const Text('CupertinoTextFormFieldRow'),
              CupertinoTextFormFieldRow(
                toolbarOptions: const ToolbarOptions(
                  cut: true,
                  copy: true,
                  paste: true,
                  selectAll: false,
                ),
              ),
            ],
          ),
        ),
      ),
    ),
  );
}
}
flutter doctor -v

Stable

[✓] Flutter (Channel stable, 3.7.0, on macOS 13.0.1 22A400 darwin-arm64, locale en-GB)
  • Flutter version 3.7.0 on channel stable at /Users/ksokolovskyi/dev/flutter
  • Upstream repository https://github.com/flutter/flutter.git
  • Framework revision b06b8b2710 (8 days ago), 2023-01-23 16:55:55 -0800
  • Engine revision b24591ed32
  • Dart version 2.19.0
  • DevTools version 2.20.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
  • Android SDK at /Users/ksokolovskyi/Library/Android/sdk
  • Platform android-33, build-tools 33.0.1
  • ANDROID_HOME = /Users/ksokolovskyi/Library/Android/sdk
  • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
  • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
  • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
  • Xcode at /Applications/Xcode.app/Contents/Developer
  • Build 14C18
  • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
  • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
  • Android Studio at /Applications/Android Studio.app/Contents
  • Flutter plugin can be installed from:
    🔨 https://plugins.jetbrains.com/plugin/9212-flutter
  • Dart plugin can be installed from:
    🔨 https://plugins.jetbrains.com/plugin/6351-dart
  • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] VS Code (version 1.74.3)
  • VS Code at /Applications/Visual Studio Code.app/Contents
  • Flutter extension version 3.58.0

[✓] Connected device (3 available)
  • iPhone SE (3rd generation) (mobile) • 6E277068-11E0-4342-B066-0D4EF7A599EB • ios            •
    com.apple.CoreSimulator.SimRuntime.iOS-16-2 (simulator)
  • macOS (desktop)                     • macos                                • darwin-arm64   • macOS 13.0.1 22A400
    darwin-arm64
  • Chrome (web)                        • chrome                               • web-javascript • Google Chrome
    108.0.5359.98

[✓] HTTP Host Availability
  • All required HTTP hosts are available

• No issues found!

Master

[✓] Flutter (Channel master, 3.8.0-1.0.pre.32, on macOS 13.0.1 22A400 darwin-arm64, locale en-GB)
  • Flutter version 3.8.0-1.0.pre.32 on channel master at /Users/ksokolovskyi/dev/flutter_master
  • Upstream repository [email protected]:ksokolovskyi/flutter.git
  • FLUTTER_GIT_URL = [email protected]:ksokolovskyi/flutter.git
  • Framework revision f9daa9aac4 (7 hours ago), 2023-02-01 22:59:24 -0500
  • Engine revision 679c4b42e2
  • Dart version 3.0.0 (build 3.0.0-192.0.dev)
  • DevTools version 2.21.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
  • Android SDK at /Users/ksokolovskyi/Library/Android/sdk
  • Platform android-33, build-tools 33.0.1
  • ANDROID_HOME = /Users/ksokolovskyi/Library/Android/sdk
  • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
  • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
  • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
  • Xcode at /Applications/Xcode.app/Contents/Developer
  • Build 14C18
  • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
  • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
  • Android Studio at /Applications/Android Studio.app/Contents
  • Flutter plugin can be installed from:
    🔨 https://plugins.jetbrains.com/plugin/9212-flutter
  • Dart plugin can be installed from:
    🔨 https://plugins.jetbrains.com/plugin/6351-dart
  • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] VS Code (version 1.74.3)
  • VS Code at /Applications/Visual Studio Code.app/Contents
  • Flutter extension version 3.58.0

[✓] Connected device (2 available)
  • macOS (desktop) • macos  • darwin-arm64   • macOS 13.0.1 22A400 darwin-arm64
  • Chrome (web)    • chrome • web-javascript • Google Chrome 108.0.5359.98

[✓] HTTP Host Availability
  • All required HTTP hosts are available

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: text inputEntering text in a text field or keyboard related problemsf: material designflutter/packages/flutter/material repository.found in release: 3.7Found to occur in 3.7found in release: 3.8Found to occur in 3.8frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions