From baae155f9696242bf0373a5cf47a2f582ab86d44 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Wed, 21 Feb 2024 18:45:37 -0800 Subject: [PATCH 1/2] Small observations on the plugin, and test. --- .../lib/src/wakelock_plus_web_plugin.dart | 41 +++++++++---------- .../lib/src/web_impl/import_js_library.dart | 40 ++++++++++++------ .../test/wakelock_plus_web_plugin_test.dart | 13 ++++++ 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart b/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart index 297eab5..03ae7c3 100644 --- a/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart +++ b/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; -import 'package:js/js.dart'; +import 'package:js/js_util.dart'; import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interface.dart'; import 'package:wakelock_plus/src/web_impl/import_js_library.dart'; import 'package:wakelock_plus/src/web_impl/js_wakelock.dart' @@ -11,39 +11,36 @@ import 'package:wakelock_plus/src/web_impl/js_wakelock.dart' /// /// This class implements the `wakelock_plus` plugin functionality for web. class WakelockPlusWebPlugin extends WakelockPlusPlatformInterface { + /// Builds an instance of the plugin, and imports the JS implementation. + WakelockPlusWebPlugin() { + _jsLoaded = importJsLibrary( + url: 'assets/no_sleep.js', flutterPluginName: 'wakelock_plus'); + } + + // The future that signals when the JS is loaded. + // This needs to be `await`ed before accessing any methods of the + // JS-interop layer. + Future? _jsLoaded; + /// Registers [WakelockPlusWebPlugin] as the default instance of the /// [WakelockPlatformInterface]. static void registerWith(Registrar registrar) { - // Import a version of `NoSleep.js` that was adjusted for the wakelock - // plugin. - importJsLibrary( - url: 'assets/no_sleep.js', flutterPluginName: 'wakelock_plus'); - WakelockPlusPlatformInterface.instance = WakelockPlusWebPlugin(); } @override Future toggle({required bool enable}) async { + // Await _jsLoaded before accessing wakelock_plus_web + await _jsLoaded!; + wakelock_plus_web.toggle(enable); } @override Future get enabled async { - final completer = Completer(); - - wakelock_plus_web.enabled().then( - // onResolve - allowInterop((value) { - assert(value is bool); - - completer.complete(value); - }), - // onReject - allowInterop((error) { - completer.completeError(error); - }), - ); - - return completer.future; + await _jsLoaded!; + + // Can be simplified a lot + return promiseToFuture(wakelock_plus_web.enabled()); } } diff --git a/wakelock_plus/lib/src/web_impl/import_js_library.dart b/wakelock_plus/lib/src/web_impl/import_js_library.dart index aa587ca..df13569 100644 --- a/wakelock_plus/lib/src/web_impl/import_js_library.dart +++ b/wakelock_plus/lib/src/web_impl/import_js_library.dart @@ -1,4 +1,5 @@ import 'dart:html' as html; +import 'dart:ui_web' as ui_web; /// This is an implementation of the `import_js_library` plugin that is used /// until that plugin is migrated to null safety. @@ -6,24 +7,29 @@ import 'dart:html' as html; /// Imports a JS script file from the given [url] given the relative /// [flutterPluginName]. -void importJsLibrary({required String url, String? flutterPluginName}) { +/// +/// Returns a Future that resolves when the library is loaded. +Future importJsLibrary({required String url, String? flutterPluginName}) { if (flutterPluginName == null) { - _importJSLibraries([url]); - } else { - _importJSLibraries([_libraryUrl(url, flutterPluginName)]); + return _importJSLibraries([url]); } + return _importJSLibraries([_libraryUrl(url, flutterPluginName)]); } String _libraryUrl(String url, String pluginName) { - if (url.startsWith('./')) { - url = url.replaceFirst('./', ''); - return './assets/packages/$pluginName/$url'; - } - if (url.startsWith('assets/')) { - return './assets/packages/$pluginName/$url'; - } else { - return url; - } + return ui_web.assetManager.getAssetUrl(url); + // + // TODO: Fix this properly! + // + // if (url.startsWith('./')) { + // url = url.replaceFirst('./', ''); + // return './assets/packages/$pluginName/$url'; + // } + // if (url.startsWith('assets/')) { + // return './assets/packages/$pluginName/$url'; + // } else { + // return url; + // } } html.ScriptElement _createScriptTag(String library) { @@ -46,6 +52,14 @@ Future _importJSLibraries(List libraries) { final scriptTag = _createScriptTag(library); head!.children.add(scriptTag); loading.add(scriptTag.onLoad.first); + // Recommended: add an onError listener to know that something + // went wrong here, rather than swallowing the problem. + scriptTag.onError.listen((html.Event e) { + final String src = (e.target as html.ScriptElement).src; + loading.add(Future.error( + Exception('Error loading: $src') + )); + }); } } diff --git a/wakelock_plus/test/wakelock_plus_web_plugin_test.dart b/wakelock_plus/test/wakelock_plus_web_plugin_test.dart index f5d9ebe..dc21aca 100644 --- a/wakelock_plus/test/wakelock_plus_web_plugin_test.dart +++ b/wakelock_plus/test/wakelock_plus_web_plugin_test.dart @@ -6,6 +6,14 @@ import 'package:wakelock_plus/src/wakelock_plus_web_plugin.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interface.dart'; +// This test could be run with: +// flutter run test --platform chrome +// But there's something weird about the JS not loading. +// +// The test can be manually run with: +// flutter run -d chrome test/wakelock_plus_web_plugin_test.dart +// or: +// with -d web-server to run it in other browsers. void main() { group('$WakelockPlusWebPlugin', () { setUpAll(() async { @@ -28,6 +36,7 @@ void main() { }); test('disable', () async { + await WakelockPlus.enable(); await WakelockPlus.disable(); expect(WakelockPlus.enabled, completion(isFalse)); }); @@ -36,6 +45,10 @@ void main() { await WakelockPlus.toggle(enable: true); expect(WakelockPlus.enabled, completion(isTrue)); + // toggle(false) fails after toggle(true). + // (This seems like a no_sleep.js issue.) + // You can see this same failure by calling `WakelockPlus.enable()` + // right before `disable()` in the test above. await WakelockPlus.toggle(enable: false); expect(WakelockPlus.enabled, completion(isFalse)); }); From ff977f50993aff1fb734da1716538aaa6a939c58 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Wed, 21 Feb 2024 19:30:49 -0800 Subject: [PATCH 2/2] Move assets into `lib`?? See: https://stackoverflow.com/questions/54740732/how-to-add-assets-in-flutter-package-plugin-development --- wakelock_plus/{ => lib}/assets/no_sleep.js | 0 wakelock_plus/lib/src/wakelock_plus_web_plugin.dart | 2 +- wakelock_plus/pubspec.yaml | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) rename wakelock_plus/{ => lib}/assets/no_sleep.js (100%) diff --git a/wakelock_plus/assets/no_sleep.js b/wakelock_plus/lib/assets/no_sleep.js similarity index 100% rename from wakelock_plus/assets/no_sleep.js rename to wakelock_plus/lib/assets/no_sleep.js diff --git a/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart b/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart index 03ae7c3..401bc23 100644 --- a/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart +++ b/wakelock_plus/lib/src/wakelock_plus_web_plugin.dart @@ -14,7 +14,7 @@ class WakelockPlusWebPlugin extends WakelockPlusPlatformInterface { /// Builds an instance of the plugin, and imports the JS implementation. WakelockPlusWebPlugin() { _jsLoaded = importJsLibrary( - url: 'assets/no_sleep.js', flutterPluginName: 'wakelock_plus'); + url: 'packages/wakelock_plus/assets/no_sleep.js', flutterPluginName: 'wakelock_plus'); } // The future that signals when the JS is loaded. diff --git a/wakelock_plus/pubspec.yaml b/wakelock_plus/pubspec.yaml index a03c573..d152357 100644 --- a/wakelock_plus/pubspec.yaml +++ b/wakelock_plus/pubspec.yaml @@ -99,4 +99,5 @@ flutter: # https://flutter.dev/custom-fonts/#from-packages assets: - - assets/no_sleep.js + - lib/assets/no_sleep.js + - packages/wakelock_plus/assets/no_sleep.js