Skip to content

[web] Use ShadowDOM slots to render HtmlElementViews #80524

Closed
flutter/website
#5928

Description

@ditman

This is an umbrella task/progress report of this design doc: Using slot to embed web Platform Views.

A partial breakdown of the tasks:

  • Wrap contents of scene in a ShadowDOM.
  • Add flag to opt-into the new rendering mechanism. DO WE WANT THIS?? NO
  • Render views into the DOM in an unified way (this code should be identical both for canvaskit and html backends, since we're rendering outside of the ShadowDOM.
    • Render SLOT on canvaskit backend
    • Render SLOT on html backend
  • Testing. WIP PR.

Activity

  1. added
    engineflutter/engine related. See also e: labels.
    a: platform-viewsEmbedding Android/iOS views in Flutter apps
    platform-webWeb applications specifically
    P1High-priority issues at the top of the work list
    on Apr 15, 2021
  2. self-assigned this
    on Apr 15, 2021
  3. ludwiktrammer commented on Apr 16, 2021

    @ludwiktrammer
  4. ditman commented on Apr 16, 2021

    @ditman
    Author
  5. ludwiktrammer commented on Apr 16, 2021

    @ludwiktrammer
  6. gib40f commented on Apr 19, 2021

    @gib40f
  7. ditman commented on Apr 19, 2021

    @ditman
    MemberAuthor

    @gib40f the code is still not in master, so you probably fixed something on your end (probably the page layout) :)

  8. ditman commented on Apr 19, 2021

    @ditman
    MemberAuthor

    I've deployed the example app in #71888 with the fix I'm working on, and it looks much more stable! The youtube video is not reloading anymore!

    I've also deployed both repro app from #77369, and looks like it's not refreshing the PDF preview:

    Last but not least, the repro app in #75195 also seemed to be affected by this issue. I've deployed it with the new engine here:

  9. ditman commented on Apr 19, 2021

    @ditman
    MemberAuthor

    ❓ Question to anybody following: Would it be useful to have a flag to enable/disable the slot-based rendering of Platform Views?

    "Disable" would mean to keep the current (buggy) version of the rendering, with the problems described in the design doc, and having to opt-in (at flutter build time) into the fix with something like:

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

    Since the current version is not working well, except for the simplest of cases, the alternative we were thinking of is to just move on with a direct fix (no need to opt-in).

    We still don't foresee any major breakage with the new structure, unless your code is using 3rd party JS code to access the contents of your platform views.

    What do you think?

  10. creativecreatorormaybenot commented on Apr 19, 2021

    @creativecreatorormaybenot
    Contributor

    What do you think?

    The upside is that in case it does break existing behavior, you would still have adjustment time / a way to use the old behavior.

    On the flip side, I really cannot imagine an actual use case that would break by fixing the bugs. If there really are no side effects, it seems like it should be fine to just move to it.

    Both of the workarounds I built over the past months, i.e. one for the HTML renderer and one for CanvasKit, should still continue to work with slots (one inserts an <iframe> element that it speaks to using post message and the other one inserts a <div> element directly in the <body>).

  11. gib40f commented on Apr 19, 2021

    @gib40f
  12. 56 remaining items

  13. Akshaymain commented on Jun 10, 2021

    @Akshaymain
  14. TahaTesser commented on Jun 10, 2021

    @TahaTesser
  15. tneotia commented on Jun 10, 2021

    @tneotia
  16. bsp003 commented on Jun 11, 2021

    @bsp003

    @ditman Can i know when will it be moved to stable channel?

    @ditman Yes, desperately in need of this in stable channel. Please help!

  17. ditman commented on Jun 23, 2021

    @ditman
    MemberAuthor
  18. jeannelim commented on Jul 12, 2021

    @jeannelim

    Any updates on this fix? Looks like it's still in master channel. We really need this fix.

  19. isamuninja commented on Jul 17, 2021

    @isamuninja

    Hello @ditman, good job.

    Switching to the beta or dev channel solves the problem when resizing the window.

    But in my case I have a problem when I try to draw an iframe or webview tag with the Element.html() method, example

    ui.platformViewRegistry.registerViewFactory(
      'hello-web',
      (int viewId) => dom.Element.html(
          '<iframe src="https://www.youtube.com/embed/NpEaa2P7qZI" height="150" width="640"></iframe>',
          validator: new dom.NodeValidatorBuilder()
            ..allowHtml5()
            ..allowElement('webview', attributes: ['*'])
            ..allowElement('iframe', attributes: ['*']))
        ..style.width = '100%'
        ..style.height = '100%',
    );
    
    Padding(
      padding: EdgeInsets.all(25),
      child: SizedBox(
        width: 640,
        height: 360,
        child: HtmlElementView(key: UniqueKey(), viewType: 'hello-web'),
      ),
    ),

    Using the basic example of flutter and adding this html element, every time I click the button to increase the element is repainted.

    I use it because I want to embed the website in an electronjs application and be able to use the webview tag which works fine for me, it only has the mentioned error.

    Do you know any way to fix this?

    I attach the complete code used.
    Demo DartPad

    import 'package:flutter/material.dart';
    import 'dart:html' as dom;
    import 'dart:ui' as ui;
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      initState() {
        super.initState();
    
        // ignore: undefined_prefixed_name
        ui.platformViewRegistry.registerViewFactory(
          'hello-web',
          (int viewId) => dom.Element.html(
              '<iframe src="https://www.youtube.com/embed/NpEaa2P7qZI" height="150" width="640"></iframe>',
              validator: new dom.NodeValidatorBuilder()
                ..allowHtml5()
                ..allowElement('webview', attributes: ['*'])
                ..allowElement('iframe', attributes: ['*']))
            ..style.width = '100%'
            ..style.height = '100%',
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                Padding(
                  padding: EdgeInsets.all(25),
                  child: SizedBox(
                    width: 640,
                    height: 360,
                    child: HtmlElementView(key: UniqueKey(), viewType: 'hello-web'),
                  ),
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    Screen.Recording.2021-07-17.at.05.57.51.mov

    Thank you so much.

  20. ditman commented on Jul 19, 2021

    @ditman
    MemberAuthor

    @isamuninja I haven't tried your code, but can you try removing the UniqueKey from the key of the video player? Every time that you set state, you're telling the framework that the video player is a different widget, and that's probably causing the repaint:

    child: HtmlElementView(key: UniqueKey(), viewType: 'hello-web'),

    to

    child: HtmlElementView(viewType: 'hello-web'),

    (I'd also move the registerViewFactory to a place that doesn't depend much of the widget lifecycle, as close to the main as you can, so it doesn't re-run, but this is probably not causing the issue.)

  21. isamuninja commented on Jul 19, 2021

    @isamuninja

    thank you very much @ditman, removing the key I no longer have the problem.

  22. ayazemre commented on Jul 31, 2021

    @ayazemre

    Is there any date for this to release on stable version?

  23. ditman commented on Aug 3, 2021

    @ditman
    MemberAuthor

    @ayazthemre I think this is already in the Beta channel. AFAIK there's no date for the next stable release. Beta to Stable happens around once a quarter.

  24. github-actions commented on Aug 17, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  25. locked as resolved and limited conversation to collaborators on Aug 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: platform-viewsEmbedding Android/iOS views in Flutter appsc: API breakBackwards-incompatible API changesengineflutter/engine related. See also e: labels.platform-webWeb applications specifically

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions