flutter_device_preview icon indicating copy to clipboard operation
flutter_device_preview copied to clipboard

Flutter web frame problem

Open luiz-rocha opened this issue 4 years ago • 11 comments

Using DevicePreview to run on chrome shows the following error, no device frame is shown:

══════╡ EXCEPTION CAUGHT BY RENDERING LIBRARY The following UnimplementedError was thrown during paint(): UnimplementedError The relevant error-causing widget was: CustomPaint

When the exception was thrown, this was the stack: dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 216:49 throw lib/ui/src/ui/path.dart 281:5 combine packages/device_preview/src/frames/mobile_device_frame.dart 212:14 paint packages/flutter/src/rendering/custom_paint.dart 531:12 [_paintWithPainter] packages/flutter/src/rendering/custom_paint.dart 572:7 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/proxy_box.dart 129:14 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/box.dart 2515:14 defaultPaint packages/flutter/src/rendering/stack.dart 602:5 paintStack packages/flutter/src/rendering/stack.dart 610:7 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/shifted_box.dart 70:14 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/proxy_box.dart 129:14 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 135:10 _repaintCompositedChild packages/flutter/src/rendering/object.dart 95:5 repaintCompositedChild packages/flutter/src/rendering/object.dart 201:7 [_compositeChild] packages/flutter/src/rendering/object.dart 182:7 paintChild packages/flutter/src/rendering/proxy_box.dart 129:14 paint packages/flutter/src/rendering/object.dart 391:12 pushLayer packages/flutter/src/rendering/object.dart 572:7 pushTransform packages/flutter/src/rendering/proxy_box.dart 2389:21 [_paintChildWithTransform] packages/flutter/src/rendering/proxy_box.dart 2406:17 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/proxy_box.dart 129:14 paint packages/flutter/src/rendering/proxy_box.dart 2040:11 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/box.dart 2515:14 defaultPaint packages/flutter/src/rendering/flex.dart 950:7 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/widgets/overlay.dart 737:14 paintStack packages/flutter/src/widgets/overlay.dart 747:7 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 184:12 paintChild packages/flutter/src/rendering/view.dart 213:14 paint packages/flutter/src/rendering/object.dart 2264:7 [_paintWithContext] packages/flutter/src/rendering/object.dart 135:10 _repaintCompositedChild packages/flutter/src/rendering/object.dart 95:5 repaintCompositedChild packages/flutter/src/rendering/object.dart 980:29 flushPaint packages/flutter/src/rendering/binding.dart 404:19 drawFrame packages/flutter/src/widgets/binding.dart 865:13 drawFrame packages/flutter/src/rendering/binding.dart 284:5 [_handlePersistentFrameCallback] packages/flutter/src/scheduler/binding.dart 1074:15 [_invokeFrameCallback] packages/flutter/src/scheduler/binding.dart 1013:9 handleDrawFrame packages/flutter/src/scheduler/binding.dart 822:7 dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 50:19 internalCallback The following RenderObject was being processed when the exception was fired: RenderCustomPaint#b1dd0: creator: CustomPaint ← IgnorePointer ← Positioned ← Stack ← Padding ← MobileDeviceFrame ← RepaintBoundary-[GlobalKey#69b08] ← Builder-[<'iPhone 5'>] ← FittedBox ← DecoratedBox ← Expanded-[<'Preview'>] ← Flex ← ⋯ parentData: (can use size) constraints: BoxConstraints(w=356.0, h=760.0) size: Size(356.0, 760.0) This RenderObject has no descendants. ═══════════ Another exception was thrown: UnimplementedError

════════ Exception caught by rendering library The following UnimplementedError was thrown during paint(): UnimplementedError

The relevant error-causing widget was DevicePreview When the exception was thrown, this was the stack dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 216:49 throw lib/ui/src/ui/path.dart 281:5 combine packages/device_preview/src/frames/mobile_device_frame.dart 212:14 paint packages/flutter/src/rendering/custom_paint.dart 531:12 [_paintWithPainter] packages/flutter/src/rendering/custom_paint.dart 572:7 paint ... The following RenderObject was being processed when the exception was fired: RenderCustomPaint#b1dd0 RenderObject: RenderCustomPaint#b1dd0 parentData: (can use size) constraints: BoxConstraints(w=356.0, h=760.0) size: Size(356.0, 760.0) ═══════════

════════ Exception caught by rendering library UnimplementedError The relevant error-causing widget was DevicePreview ═══════════

luiz-rocha avatar Apr 22 '20 15:04 luiz-rocha

Yes, paths aren't implemented yet with css based engine.

In the meantime, you can build against the skia based engine instead (that's what I did for the demo).

To do this build with the following command :

flutter build web --dart-define=FLUTTER_WEB_USE_SKIA=true

aloisdeniel avatar Apr 22 '20 16:04 aloisdeniel

Ouch bummer path issue here too, yes I noticed as well when I just tested this on Web and run into Path() issue in another case as well.

I just tried to build the example app with the master channel (that I have to use to be able to build for Windows), this version to be exact:

Flutter 1.19.0-2.0.pre.145 • channel master • https://github.com/flutter/flutter.git
Framework • revision af9b6a6efa (6 hours ago) • 2020-05-26 09:17:55 -0700
Engine • revision 9ce1e5c5c7
Tools • Dart 2.9.0 (build 2.9.0-10.0.dev 7706afbcf5)

I get a crash on the path there now too, oh wait, this looks like DomCanvas build. If I instead build for SKIA in release mode with:

flutter run --release --dart-define=FLUTTER_WEB_USE_SKIA=true -d Chrome

Is SKIA builds supposed to work without release mode? Earlier I read it only works in --release mode.

Now building it on master in --release mode, now it does not crash, but no deviceFrames either:

image

Now I am trying beta channel that is more official for Web builds:

Flutter 1.18.0-11.1.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision 2738a1148b (13 days ago) • 2020-05-13 15:24:36 -0700
Engine • revision ef9215ceb2
Tools • Dart 2.9.0 (build 2.9.0-8.2.beta)

Same result when building for SKIA, it crashes if not building in release mode with the additional flag --release, but that happens because it actually create a DomCanvas build then. With the --release mode flag added it does not crash, but no device frames are drawn either, like in the above image. So same result on master and beta channel.


These builds were done a Windows 10 machine, maybe it works when building on a Mac or Linux?


Also at the moment SKIA builds can really only be used for dev / experimental test builds, because at least on Windows 10 when you build for SKIA the fonts looks really bad. See this issue for more info: https://github.com/flutter/flutter/issues/56319

rydmike avatar May 26 '20 23:05 rydmike

I can confirm that it builds and doesn't crash but there are not frames with Skia.

kuhnroyal avatar May 27 '20 08:05 kuhnroyal

Not much to be done about until Flutter Web supports it, imo. Fixing it would require using some other APIs in CustomPaint that are currently supported that could be used to achieve the same end result, so probably quite a bit of work, if doable at all.

Does anybody know or have found if there is a ticket about this unsupported API open on Flutter issues already? If not, I think we should open one.

It is a bit frustrating when there is no documentation whatsoever on what APIs are currently supported or not supported on Flutter WEB and they also differ on DomCanvas and CanvasKit, not only that, in some cases where they both work, the DomCanvas can produce output that deviates significantly from the CanvasKit (and device SKIA) renderings.

But yeah, I guess there is a reason why Flutter Web is still in beta, so there is that too :)

rydmike avatar May 28 '20 08:05 rydmike

The relevant issue is https://github.com/flutter/flutter/issues/44572

kuhnroyal avatar May 28 '20 10:05 kuhnroyal

Thanks, I'll will go and up-vote it too, and say some supporting words. 😀

rydmike avatar May 28 '20 12:05 rydmike

During my last tests it worked only with CanvasKit in release mode (https://flutter-device-preview.firebaseapp.com/#/).

Maybe a regression with latest versions?

aloisdeniel avatar May 28 '20 13:05 aloisdeniel

I think so too, at least it no longer seems to work even with CanvasKit and no channel that I tried, I tried with beta and master, but not with dev.

If you have not, maybe you could consider dropping some comments/info on the issue too.

rydmike avatar May 28 '20 16:05 rydmike

I made a workaround to make it work on Flutter web for now. I don't display the notch if is on web (it has a lot of Path.combined) and instead of Path.combined between the body and screen, I use blendMode

Code starting at mobile_frame.dart#L386

    if (!kIsWeb) {
      if (device.notch != null && device.notch.width > 0) {
        final notchPath = _createNotchPath(size);
        screen = Path.combine(
          PathOperation.difference,
          screen,
          notchPath,
        );
      }
    }

    final bodyWithoutScreen =
        kIsWeb ? body : Path.combine(PathOperation.difference, body, screen);

    canvas.drawPath(
        bodyWithoutScreen,
        Paint()
          ..style = PaintingStyle.fill
          ..color = style.bodyColor);
    
   if (kIsWeb) {
      canvas.drawPath(
          screen,
          Paint()
            ..style = PaintingStyle.fill
            ..blendMode = BlendMode.dstOut);
    }

jamesblasco avatar Jul 07 '20 19:07 jamesblasco

@aloisdeniel I run locally your example app from device_preview package on web and device preview is working correctly only for devices that have notches. For those without notch black screen is displayed. I run an app with command: flutter run --release --dart-define=FLUTTER_WEB_USE_SKIA=true -d Chrome. The demo you provided is working properly for all devices. Do you know what can be a cause of that? IPHONE XS Screenshot 2020-08-13 at 12 36 15 IPHONE 5 Screenshot 2020-08-13 at 12 36 08

moniaS avatar Aug 13 '20 10:08 moniaS

@aloisdeniel I run locally your example app from device_preview package on web and device preview is working correctly only for devices that have notches. For those without notch black screen is displayed. I run an app with command: flutter run --release --dart-define=FLUTTER_WEB_USE_SKIA=true -d Chrome. The demo you provided is working properly for all devices. Do you know what can be a cause of that? IPHONE XS Screenshot 2020-08-13 at 12 36 15 IPHONE 5 Screenshot 2020-08-13 at 12 36 08

I fix it by add this code at mobile_device_frame.dart (Line 216) by this code.

if (device.notch != null && device.notch.width > 0) { // line 154
    // [dart code]
} else { // line 216
    screen = Path.combine( PathOperation.difference, screen, Path()..addRect(Offset(0, 0) & Size(0, 0),));
}// line 218

badlee avatar Sep 09 '20 03:09 badlee