the-airbender / quill_html_editor

HTML rich text editor for Android, iOS, and Web, using the QuillJS library. QuillJS is a free, open source WYSIWYG editor built for the modern web.
https://pub.dev/packages/quill_html_editor
MIT License
94 stars 91 forks source link

[BUG] Flutter web getting this issue with color picker or tooltip overlay #195

Open Raviteja11122 opened 5 months ago

Raviteja11122 commented 5 months ago

======== Exception caught by gesture =============================================================== The following assertion was thrown while handling a gesture: setState() called after dispose(): ToolBarState#e0039(lifecycle state: defunct, not mounted)

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.

The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree. This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

When the exception was thrown, this was the stack: dart-sdk/lib/_internal/js_dev_runtime/private/ddcruntime/errors.dart 297:3 throw packages/flutter/src/widgets/framework.dart 1167:9 packages/flutter/src/widgets/framework.dart 1201:14 setState packages/quill_html_editor/src/tool_bar.dart 944:11 packages/quill_html_editor/src/widgets/color_picker.dart 29:36 packages/flutter/src/gestures/recognizer.dart 315:24 invokeCallback packages/flutter/src/gestures/tap.dart 652:11 handleTapUp packages/flutter/src/gestures/tap.dart 309:5 [_checkUp] packages/flutter/src/gestures/tap.dart 242:7 handlePrimaryPointer packages/flutter/src/gestures/recognizer.dart 670:9 handleEvent packages/flutter/src/gestures/pointer_router.dart 98:7 [_dispatch] packages/flutter/src/gestures/pointer_router.dart 143:9 dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 21:7 forEach packages/flutter/src/gestures/pointer_router.dart 141:17 [_dispatchEventToRoutes] packages/flutter/src/gestures/pointer_router.dart 127:7 route packages/flutter/src/gestures/binding.dart 495:5 handleEvent packages/flutter/src/gestures/binding.dart 475:14 dispatchEvent packages/flutter/src/rendering/binding.dart 430:11 dispatchEvent packages/flutter/src/gestures/binding.dart 420:7 [_handlePointerEventImmediately] packages/flutter/src/gestures/binding.dart 383:5 handlePointerEvent packages/flutter/src/gestures/binding.dart 330:7 [_flushPointerEventQueue] packages/flutter/src/gestures/binding.dart 299:9 [_handlePointerDataPacket] lib/_engine/engine/platform_dispatcher.dart 1361:5 invoke1 lib/_engine/engine/platform_dispatcher.dart 286:5 invokeOnPointerDataPacket lib/_engine/engine/pointer_binding.dart 398:30 [_sendToFramework] lib/_engine/engine/pointer_binding.dart 224:7 onPointerData lib/_engine/engine/pointer_binding.dart 1001:20 lib/_engine/engine/pointer_binding.dart 930:7 lib/_engine/engine/pointer_binding.dart 531:9 loggedHandler dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 550:37 _checkAndCall dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 555:39 dcall Handler: "onTap" Recognizer: TapGestureRecognizer#dbe8e debugOwner: GestureDetector state: possible won arena finalPosition: Offset(685.1, 377.0) finalLocalPosition: Offset(11.4, 16.0) button: 1 sent tap down

Raviteja11122 commented 5 months ago

This is happening with the OverlayEntryHidden not being removed from the screen,

Error reproducible scenario,

I'm using pageview on the screen and one of the pages has QuilEditor whenever I navigate directly to the last page. Eltooltip widget inserts hidden overlay that's not removed because of the below condition.

void _getHiddenOverlaySize(context) {
    RenderBox box = _widgetKey.currentContext?.findRenderObject() as RenderBox;
    if (mounted) {
      setState(() {
        _overlayBox = ElementBox(
          w: box.size.width,
          h: box.size.height,
        );
        _overlayEntryHidden?.remove();
      });
    }
  }

After the below changes this issue is not reproduced

Eltooltip.dart

void _getHiddenOverlaySize(context) {
    RenderBox box = _widgetKey.currentContext?.findRenderObject() as RenderBox;
    if (mounted) {
      setState(() {
        _overlayBox = ElementBox(
          w: box.size.width,
          h: box.size.height,
        );
      });
    }
    if(_overlayEntryHidden != null) {
      _overlayEntryHidden?.remove();
      _overlayEntryHidden = null;
    }
  }

toolbar.dart (setState is guarded with mounted condition)

content: ColorPicker(
        onColorPicked: (color) {
          _formatMap['color'] = color;
          _toolbarList[i] = _toolbarList[i].copyWith(isActive: true);
          widget.controller
              .setFormat(format: 'color', value: _formatMap['color']);
          if(mounted) {
            setState(() {});
          }
          if (_fontColorKey.currentState != null) {
            _fontColorKey.currentState!.hideOverlay();
          }
        },
      ),