flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
164.55k stars 27.13k forks source link

[web_html] Dimissible widget not rendering properly, had weird artifact when dragging, keyboard doesn't pop when focus on textfield #79087

Open ernestrlee opened 3 years ago

ernestrlee commented 3 years ago

Steps to Reproduce

  1. Run flutter create bug.
  2. Update the files as follows: ...
  3. My prototype web app, which was deployed to the web after uploading the build/web folder to AWS Amplify, does not appear to work when using mobile device browsers (Chrome on Android or iOS). The app will crash at a certain point and will not display text in other parts where it is supposed to. The web app works fine when using a desktop on Chrome. It also works as a stand alone mobile app on iOS and Android. Here is the link for the prototype web app: https://mkcapp.app2playdev.com

Expected results: The web app should work consistently and should not depend on what the device/browser is.

Actual results: The app was crashing at certain points in the app and was not displaying text correctly in other areas. Example, in the recipe converter, text was not displayed for mobile devices. In the recipe converter, the app was crashing after attempting to convert the recipe. This worked fine on desktop web and in development for Android/iOS mobile devices. This does not work for mobile accessing the web app.

Logs N/A N/A ``` [√] Flutter (Channel stable, 2.0.3, on Microsoft Windows [Version 10.0.19042.867], locale en-US) • Flutter version 2.0.3 at C:\src\flutter • Framework revision 4d7946a68d (7 days ago), 2021-03-18 17:24:33 -0700 • Engine revision 3459eb2436 • Dart version 2.12.2 [√] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at C:\Users\MKC\AppData\Local\Android\sdk • Platform android-30, build-tools 30.0.3 • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe [√] Android Studio (version 4.1.0) • Android Studio at C:\Program Files\Android\Android Studio • 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 1.8.0_242-release-1644-b01) [√] VS Code (version 1.54.3) • VS Code at C:\Users\MKC\AppData\Local\Programs\Microsoft VS Code • Flutter extension version 3.20.0 [√] Connected device (2 available) • Chrome (web) • chrome • web-javascript • Google Chrome 89.0.4389.90 • Edge (web) • edge • web-javascript • Microsoft Edge 89.0.774.57 • No issues found! ```
TahaTesser commented 3 years ago

Hi @ernestrlee Can you please provide a minimal complete reproducible code sample instead of deployed app? Thank you

ernestrlee commented 3 years ago

Hello Taha,

Sure, I'll attach minimal code here. lib.zip

After looking at the issue, it may have something to do with the rich text or widget spans. It is also causing issues with swipe to delete on browsers. I'm not sure why it works on desktop browser, iOS, and Android, but it does not work mobile browser. I deployed to firebase and also got the same issue.

Thanks!

TahaTesser commented 3 years ago

Hi @ernestrlee Thanks for the code sample, I can see text rendering issue when using you code sample on the mobile web from stable to dev channels, only master works. Is it the same issue as yours?

but I am not sure what the exact issue you're describing here, can you please explain the issue in detail

After looking at the issue, it may have something to do with the rich text or widget spans. It is also causing issues with swipe to delete on browsers.

Here I deployed and tested on Chrome on Android and iOS The text doesn't render properly, only shows when tapping in the area

stable https://gracious-panini-5a8551.netlify.app/ beta https://admiring-dijkstra-d0036f.netlify.app/ dev https://romantic-bohr-9570fd.netlify.app/#/ master https://distracted-fermat-30f9ab.netlify.app/

flutter doctor -v ```bash [✓] Flutter (Channel stable, 2.0.3, on macOS 11.2.3 20D91 darwin-x64, locale en-GB) • Flutter version 2.0.3 at /Users/tahatesser/Code/flutter_stable • Framework revision 4d7946a68d (10 days ago), 2021-03-18 17:24:33 -0700 • Engine revision 3459eb2436 • Dart version 2.12.2 [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Volumes/Extreme/SDK • Platform android-30, build-tools 30.0.3 • ANDROID_HOME = /Volumes/Extreme/SDK • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • 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 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.54.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.20.0 [✓] Connected device (3 available) • iPhone 12 (mobile) • 83060656-28E7-44CD-801E-B11EC3EC89BA • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-4 (simulator) • macOS (desktop) • macos • darwin-x64 • macOS 11.2.3 20D91 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 89.0.4389.90 • No issues found! ``` ```bash [✓] Flutter (Channel beta, 2.1.0-12.2.pre, on macOS 11.2.3 20D91 darwin-x64, locale en-GB) • Flutter version 2.1.0-12.2.pre at /Users/tahatesser/Code/flutter_beta • Framework revision 5bedb7b1d5 (11 days ago), 2021-03-17 17:06:30 -0700 • Engine revision 711ab3fda0 • Dart version 2.13.0 (build 2.13.0-116.0.dev) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Volumes/Extreme/SDK • Platform android-30, build-tools 30.0.3 • ANDROID_HOME = /Volumes/Extreme/SDK • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • 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 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.54.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.20.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-x64 • macOS 11.2.3 20D91 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 89.0.4389.90 • No issues found! ``` ```bash [✓] Flutter (Channel dev, 2.1.0-12.1.pre, on macOS 11.2.3 20D91 darwin-x64, locale en-GB) • Flutter version 2.1.0-12.1.pre at /Users/tahatesser/Code/flutter_dev • Framework revision 8264cb3e8a (3 weeks ago), 2021-03-10 12:37:57 -0800 • Engine revision 711ab3fda0 • Dart version 2.13.0 (build 2.13.0-116.0.dev) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Volumes/Extreme/SDK • Platform android-30, build-tools 30.0.3 • ANDROID_HOME = /Volumes/Extreme/SDK • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • 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 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.54.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.20.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-x64 • macOS 11.2.3 20D91 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 89.0.4389.90 • No issues found! ``` ```bash [✓] Flutter (Channel master, 2.1.0-13.0.pre.294, on macOS 11.2.3 20D91 darwin-x64, locale en-GB) • Flutter version 2.1.0-13.0.pre.294 at /Users/tahatesser/Code/flutter_master • Framework revision a603714610 (22 hours ago), 2021-03-28 03:54:02 -0700 • Engine revision b5e15d055d • Dart version 2.13.0 (build 2.13.0-162.0.dev) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Volumes/Extreme/SDK • Platform android-30, build-tools 30.0.3 • ANDROID_HOME = /Volumes/Extreme/SDK • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • 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 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.54.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.20.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-x64 • macOS 11.2.3 20D91 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 89.0.4389.90 • No issues found! ```

Thank you

ernestrlee commented 3 years ago

Hello Taha,

Thanks for looking into this.
I have tried the above links and they have the same issues. It works for desktop Chrome, but not mobile Chrome.

This is how the code is supposed to work:

  1. I have a widget called transformer text field. This widget has two visibility states. The first state shows a text widget comprised of rich text. The second state shows an edit text field so the user can edit the text. When the user wants to change the text in the list, they click on the text widget. This causes the widget to change it's visibility state and the edit text appears. Upon pressing enter or changing focus, the edit text changes visibility and the text widget becomes visible again.
  2. After changing focus or pressing enter on the edit text, the text in the edit text goes into a "transform text" function. In this case, I am applying a text span widget for every 3rd letter and styling it with a yellow box. This gets wrapped in a rich text widget and is then used to populate the list item.
  3. The issue is, this will not work on Chrome when using iOS or Android mobile devices (iPad, phone, etc). It will only work when using Chrome on desktops such as windows and possibly MAC.
  4. When I deploy the app as a native iOS app or native Android app, I do not have this issue. The text shows up fine and my app works great. This issue only pertains to it not working on iOS or Android device when using Chrome as a web app.

Please try opening this in a desktop with Chrome browser to see if it works. Then try a mobile device and see that it does not work. This may suggest there is something in the Flutter framework for the web portion may not be handling this properly since it is inconsistent between devices.

Thanks,

Ernest

TahaTesser commented 3 years ago

Hi @ernestrlee Thanks for the explanation, did you try the master link from https://github.com/flutter/flutter/issues/79087#issuecomment-809191675, i can see same behavior when using master on chrome on android or iOS as on desktop

stable master
ezgif com-gif-maker ezgif com-gif-maker (1)

Can you please confirm you get the same result? Thank you

ernestrlee commented 3 years ago

Hello Taha,

Thanks for confirming that there seems to be an issue on some of the channels. I have tried the master channel and the rich text seems to appear fine. However, there are two additional issues that I notice.

1) When I swipe to delete, there are issues when I don't delete the item. The red highlight background sometimes appears over the other items when you partially drag but do not delete. Try dragging partially from top to bottom without deleting.

2) The other item I noticed when I focus on an edit text is that my onscreen keyboard on iOS Chrome browser does not popup, so I can't type anything. This onscreen keyboard issue appears for iPad and iPhone, but looks okay for my Android device.

Thanks,

Ernest

TahaTesser commented 3 years ago

Hi @ernestrlee Thanks for the confirmation!

  1. I can reproduce the issue only Android

preview
ezgif com-gif-maker (10)
  1. When you tap to transform text, the keyboard isn't opened but if you double-tap, the on-screen keyboard appears, it's not just chrome but also on Safari. Can you confirm this behavior?

preview
TahaTesser commented 3 years ago

Also, I just arranged all your classes into a runnable code sample for anyone fixing this issue

complete code sample ```dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'dart:collection'; import 'package:flutter/foundation.dart'; void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => ListData()), ], child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { @override Widget build(BuildContext context) { return MyList(); } } class ListData extends ChangeNotifier { List _list = [ 'Apple', 'Broccoli', 'Flour', 'Cabbage', ]; UnmodifiableListView get list { return UnmodifiableListView(_list); } void addItem(String item) { _list.add(item); notifyListeners(); } void removeItem(int index) { if (index >= 0 && index < list.length) { _list.removeAt(index); } notifyListeners(); } void updateItem(int index, String str) { if (index >= 0 && index < list.length) { _list[index] = str; //notifyListeners(); } } void updateList(List list) { _list = list; notifyListeners(); } void clearList() { _list = []; notifyListeners(); } } class MyList extends StatefulWidget { @override _MyListState createState() => _MyListState(); } class _MyListState extends State { // This function updates the text used in the textfield void _updateText(int index, String str) { Provider.of(context, listen: false).updateItem(index, str); } void _deleteItem(int index) { Provider.of(context, listen: false).removeItem(index); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { FocusScope.of(context).unfocus(); }, child: Scaffold( body: Container( margin: EdgeInsets.all(20), child: Column( children: List.generate( Provider.of(context).list.length, (index) => TransformerTextField( key: ValueKey( '${Provider.of(context).list[index]}$index'), index: index, text: Provider.of(context).list[index], onTransform: capSpan, onDelete: _deleteItem, onUpdate: _updateText, ), ), ), ), ), ); } } class TransformerTextField extends StatefulWidget { final int? index; final String? text; final Function? onTransform; final Function? onUpdate; final Function? onDelete; final Key? key; TransformerTextField( {this.index, this.text, this.onTransform, this.onUpdate, this.onDelete, this.key}); @override _TransformerTextFieldState createState() => _TransformerTextFieldState(); } class _TransformerTextFieldState extends State { bool isEnabled = false; TextEditingController _controller = TextEditingController(); FocusNode? _focusNode; @override void initState() { super.initState(); _controller.text = widget.text!; _focusNode = FocusNode(); _focusNode!.addListener(_onFocusChange); } @override void dispose() { _controller.dispose(); _focusNode!.removeListener(_onFocusChange); _focusNode!.dispose(); super.dispose(); } void _onFocusChange() { if (_focusNode!.hasPrimaryFocus) { setState(() { // Toggle to texfield view isEnabled = true; // Populate the texfield with the text _controller.text = widget.text!; // Start cursor at end of text when tapped on _controller.selection = TextSelection.fromPosition( TextPosition(offset: _controller.text.length)); }); } else { // Update the original text value _updateText(); setState(() { // Toggle to the text view isEnabled = false; }); } } void _updateText() { widget.onUpdate!(widget.index, _controller.text); } @override Widget build(BuildContext context) { return Container( key: widget.key, child: Visibility( visible: isEnabled, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0), child: TextField( decoration: InputDecoration( border: InputBorder.none, ), style: TextStyle( fontSize: 16, height: 1.8, ), focusNode: _focusNode, controller: _controller, autofocus: true, keyboardType: TextInputType.text, maxLines: null, ), ), ), ], ), replacement: GestureDetector( onTap: () { setState(() { isEnabled = true; _focusNode!.requestFocus(); }); }, child: Dismissible( key: UniqueKey(), onDismissed: (direction) { widget.onDelete!(widget.index); }, background: Container( decoration: BoxDecoration( color: Colors.red, ), child: Padding( padding: const EdgeInsets.all(10.0), child: Align( alignment: Alignment.centerRight, child: Text( 'Delete', style: TextStyle( color: Colors.white, ), ), ), ), ), direction: DismissDirection.endToStart, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Padding( padding: const EdgeInsets.all(10.0), child: widget.onTransform!(context, _controller.text), ), ), ], ), ), ), ), ); } } Widget capSpan(BuildContext context, String str) { List output = []; for (int i = 0; i < str.length; i++) { if (i % 3 == 0) { output.add(buildTaggedTextWidgetSpan(context, str[i])); } else { output.add(buildTextWidgetSpan(context, str[i])); } } return RichText( text: TextSpan( text: '', children: output, ), ); } WidgetSpan buildTaggedTextWidgetSpan(BuildContext context, String str, [TextStyle? style]) { return WidgetSpan( child: Container( margin: EdgeInsets.only(right: 4), decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(5.0), //backgroundBlendMode: BlendMode.dst, ), padding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 3), child: Text( str, style: style ?? TextStyle( fontSize: 16, ), ), ), ); } WidgetSpan buildTextWidgetSpan( BuildContext context, String str, [ TextStyle style = const TextStyle( fontSize: 16, ), ]) { return WidgetSpan( child: Container( padding: EdgeInsets.only(top: 5.0, bottom: 5, right: 4.0), child: Text( str, style: style, ), ), ); } ```
ernestrlee commented 3 years ago

Hello Taha,

Thanks for confirming the issues. On the drag to dismiss/delete, the behavior is even more confusing if you go from one item to the next. The entire list becomes red for the items that were dragged previously.

As for the double tap, I tried on my iOS device and confirmed that the keyboard does pop up after a double tap. This may suggest that there may be something wrong with the autofocus, since the keyboard should pop up upon focus.

Thanks again for your assistance in looking into this.

Ernest Lee

TahaTesser commented 3 years ago

Hi @ernestrlee Let's summarise the issue since there is a lot going on. These could be different issues or the same, I am not sure

Text Rendering issue

Results

Note: If you don't specify --web-renderer when building app flutter build web, mobile web is rendered in html and canvaskit on desktop. If you explicitly provide web renderer, you will see some results on desktop and mobile flutter build web --web-renderer html

HTML

So when building for mobile and desktop in html, code isn't properly rendered from stable to dev channels, the page looks blank but it's not, you can see debug banner and editable text is visible when you tap in the area

ezgif com-gif-maker (12)

This issue only reproduced from stable to dev, text is rendering fine on master channel

Refer to https://github.com/flutter/flutter/issues/79087#issuecomment-809191675

Canvaskit

Renders on both desktop and mobile as expected on all channels

Which makes this issue only related html renderer

Weird artifacts with Dismissible

When dragging Dismissible on Android (I haven't noticed this issue on iOS), we get red lines, sometimes multiple red lines

red highlight background sometimes appears over the other items when you partially drag but do not delete. Try dragging partially from top to bottom without deleting.

I wasn't able to verify this Please provide steps to reproduce this if possible

113105966-dec96180-920a-11eb-8a31-7d0bfbcb0a85

Keyboard doesn't popup on iOS

Code sample has two states when entering the editable state, the cursor is visible but the keyboard doesn't pop up until double-tap on iOS

113106363-5ac3a980-920b-11eb-8c61-d135dd150f3b

Let me know if this summary is satisfying to you

ernestrlee commented 3 years ago

Hello Taha,

Thank you for putting together the summary. This looks correct, except for the description for the dismissible bug. It also is seen on my Android device. When I drag left, but not all the way, and I move to the next item in the list, and drag but not all the way, the items that were previously dragged all turn red at the same time. You can see this when you do it to each of the items in the list. Try dragging on each item in the list.

Thanks,

Ernest

TahaTesser commented 3 years ago

Hi @ernestrlee Thanks for the confirmation, I'm unable to reproduce the "all turn red" issue on a physical device or emulator

Code Sample

https://github.com/flutter/flutter/issues/79087#issuecomment-810842779

Issue summary

https://github.com/flutter/flutter/issues/79087#issuecomment-811727143

ernestrlee commented 3 years ago

Hello Taha,

The below clip is what I am seeing. This happens on all devices I have tested, including emulator.

https://user-images.githubusercontent.com/30732731/113555857-6965e400-95b0-11eb-94f9-fab3758ff817.mp4

Thanks,

Ernest

TahaTesser commented 3 years ago

@ernestrlee Ah, I can finally also reproduce that, thanks for the video