Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dart:html] document.onFullscreenChange no longer provides events from the DOM #49374

Closed
navaronbracke opened this issue Jul 1, 2022 · 6 comments
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-libraries Issues impacting dart:html, etc., libraries web-triage-0 repro is available

Comments

@navaronbracke
Copy link

navaronbracke commented Jul 1, 2022

Steps to reproduce

  1. flutter create myapp
  2. Update main.dart with the code sample
  3. Add the code sample for fullscreen_service.dart so that you have
lib/
- main.dart
- fullscreen_service.dart
  1. flutter run -d chrome (as this sample uses dart:html)
  2. Press the button to toggle fullscreen
  3. The app goes into fullscreen
  4. The notifier does not get updated and the print in the listener never happens
  5. Press escape to exit fullscreen
  6. The notifier still does not get updated, nor does the print happen

Cause of the problem: For some reason the handler for document.onFullscreenChange never fires.

Code sample

main.dart

import 'package:flutter/material.dart';

import 'package:fullscreen_test/fullscreen_service.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final service = FullscreenService();

  Widget _buildFullscreenWidget() {
    if (service.isSupported) {
      return AnimatedBuilder(
        animation: service.isFullscreen,
        builder: (context, child) {
          final bool isFullscreen = service.isFullscreen.value;

          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Is currently in fullscreen? $isFullscreen'),
              ElevatedButton(
                onPressed: () async {
                  if (isFullscreen) {
                    await service.exitFullscreen();
                  } else {
                    await service.enterFullscreen();
                  }
                },
                child: const Text('Toggle fullscreen'),
              ),
            ],
          );
        },
      );
    }

    return const Text('Fullscreen is not supported');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(child: _buildFullscreenWidget()),
    );
  }

  @override
  void dispose() {
    service.dispose();
    super.dispose();
  }
}

fullscreen_service.dart

import 'dart:async';

// ignore: avoid_web_libraries_in_flutter
import 'dart:html';

import 'package:flutter/foundation.dart';

class FullscreenService {
  FullscreenService() {
    // Handle fullscreen changes from user interaction, and the escape key.
    _fullscreenSubscription = document.onFullscreenChange.listen((event) {
      print('Fullscreen DOM event fired');
      _notifier.value = document.fullscreenElement != null;
    });
  }

  final ValueNotifier<bool> _notifier = ValueNotifier(false);

  StreamSubscription<Object>? _fullscreenSubscription;

  ValueListenable<bool> get isFullscreen => _notifier;

  bool get isSupported => document.fullscreenEnabled ?? false;

  Future<void> enterFullscreen() {
    if (isSupported && !_notifier.value) {
      document.documentElement!.requestFullscreen();
    }

    return Future<void>.value();
  }

  Future<void> exitFullscreen() {
    if (isSupported && _notifier.value) {
      document.exitFullscreen();
    }

    return Future<void>.value();
  }

  void dispose() async {
    await exitFullscreen();

    _fullscreenSubscription?.cancel();
  }
}

Reproducible on:
Chrome version: 103.0.5060.53 (Official Build) (x86_64)
Firefox version 102.0 (64-bit)

Can't reproduce since fullscreen is unsupported
Safari version: 15.3 (17612.4.9.1.8)

[✓] Flutter (Channel stable, 3.0.2, on macOS 12.2.1 21D62 darwin-x64, locale
    en-BE)
    • Flutter version 3.0.2 at /Users/navaronbracke/Documents/flutter
    • Upstream repository git@github.com:flutter/flutter.git
    • Framework revision cd41fdd495 (3 weeks ago), 2022-06-08 09:52:13 -0700
    • Engine revision f15f824b57
    • Dart version 2.17.3
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version
    32.1.0-rc1)
    • Android SDK at /Users/navaronbracke/Library/Android/sdk
    • Platform android-32, build-tools 32.1.0-rc1
    • ANDROID_HOME = /Users/navaronbracke/Library/Android/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

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

[✓] Android Studio (version 2021.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 11.0.11+0-b60-7590822)

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

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 12.2.1 21D62 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 103.0.5060.53

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

• No issues found!
@mraleph mraleph added the area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. label Jul 1, 2022
@nshahan nshahan added the web-libraries Issues impacting dart:html, etc., libraries label Jul 1, 2022
@nshahan
Copy link
Contributor

nshahan commented Jul 1, 2022

A minimal repro that reproduces with a DDC compile. There is no sign that the event is firing when going in and out of full screen. I tried on MacOS and Linux.

import 'dart:html';

main() {
  document.onFullscreenChange.listen((event) {
    print('Fullscreen DOM event fired');
  });
}

@nshahan nshahan added the web-triage-0 repro is available label Jul 1, 2022
@navaronbracke
Copy link
Author

I tried to track down where exactly the bug started happening and it turns out that somewhere between Dart 2.16.2 and Dart 2.17.0 the listener stopped working.

Dart version Listener works
2.16.2 (ref 6fbb923) yes
2.17.0 (ref 9f52c6d) no

I did not get to do a git bisect to track down the specific commit that is causing this,
I might get to that if I have the time.

Side note:
To verify where the bug happens, I used the following dependencies
These work for both Dart revisions listed above.
(I had a version conflict with more recent versions of webdev, which made me have to pin deps to run my sample)

dev_dependencies:
  build_runner: 2.2.0
  build_web_compilers: 3.2.3
  webdev: 2.7.8
  dwds: 12.0.0
  vm_service: 8.2.2

@navaronbracke
Copy link
Author

navaronbracke commented Jul 7, 2023

@nshahan with the recent work on package:web, this now works as expected if you use its bindings, which rely on static interop. So this issue can be closed.

@dxvid-pts
Copy link

dxvid-pts commented Feb 11, 2024

It doesn't work as expected on package:web as well. This is due to fullscreenChangeEvent listening to webkitfullscreenchange and not on fullscreenchange.

See /lib/src/helpers/events/providers.dart

Screenshot 2024-02-11 at 22 30 42

@nshahan
Copy link
Contributor

nshahan commented Feb 12, 2024

cc @srujzs

@srujzs
Copy link
Contributor

srujzs commented Feb 12, 2024

Filed dart-lang/web#168 to track that. Those providers are a relic of dart:html that we wanted to make migration easier, but in this case, webkitfullscreenchange doesn't even exist anymore, so we should update it.

The workaround is simple of course:EventStreamProvider<Event>('fullscreenchange').

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-libraries Issues impacting dart:html, etc., libraries web-triage-0 repro is available
Projects
None yet
Development

No branches or pull requests

5 participants