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

fix: add support for non-root base-href #75

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions wakelock_plus/example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json
!/ios/Podfile
!/ios/Podfile
23 changes: 1 addition & 22 deletions wakelock_plus/example/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,8 @@

<title>example</title>
<link rel="manifest" href="manifest.json">

<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
appRunner.runApp();
});
}
});
});
</script>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>
File renamed without changes.
32 changes: 21 additions & 11 deletions wakelock_plus/lib/src/wakelock_plus_web_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import 'dart:async';
import 'dart:js_interop';

import 'package:flutter_web_plugins/flutter_web_plugins.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'
as wakelock_plus_web;
import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interface.dart';

/// The web implementation of the [WakelockPlatformInterface].
///
Expand All @@ -14,30 +14,40 @@ class WakelockPlusWebPlugin extends WakelockPlusPlatformInterface {
/// 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.
_jsLoaded = importJsLibrary(
url: 'assets/no_sleep.js', flutterPluginName: 'wakelock_plus');

WakelockPlusPlatformInterface.instance = WakelockPlusWebPlugin();
}

// The future that resolves when the JS library is loaded.
static late Future<void> _jsLoaded;
// The future that signals when the JS is loaded.
// This needs to be `await`ed before accessing any methods of the
// JS-interop layer.
late Future<void> _jsLoaded;
bool _jsLibraryLoaded = false;

//
// Lazily imports the JS library once, then awaits to ensure that
// it's loaded into the DOM.
//
Future<void> _ensureJsLoaded() async {
if (!_jsLibraryLoaded) {
_jsLoaded = importJsLibrary(
url: 'assets/no_sleep.js', flutterPluginName: 'wakelock_plus');
_jsLibraryLoaded = true;
}
await _jsLoaded;
}

@override
Future<void> toggle({required bool enable}) async {
// Make sure the JS library is loaded before calling it.
await _jsLoaded;
await _ensureJsLoaded();

wakelock_plus_web.toggle(enable);
}

@override
Future<bool> get enabled async {
// Make sure the JS library is loaded before calling it.
await _jsLoaded;

await _ensureJsLoaded();
final completer = Completer<bool>();

wakelock_plus_web.enabled().toDart.then(
Expand Down
39 changes: 28 additions & 11 deletions wakelock_plus/lib/src/web_impl/import_js_library.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:js_interop';
import 'dart:ui_web' as ui_web;

import 'package:web/web.dart';
import 'package:web/web.dart' as web;

/// This is an implementation of the `import_js_library` plugin that is used
/// until that plugin is migrated to null safety.
Expand All @@ -18,19 +19,23 @@ Future<void> importJsLibrary(
}

String _libraryUrl(String url, String pluginName) {
// Added suggested changes as per
// https://github.com/fluttercommunity/wakelock_plus/issues/19#issuecomment-2301963609
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(
'packages/$pluginName/$url',
);
}

return url;
}

HTMLScriptElement _createScriptTag(String library) {
final script = document.createElement('script') as HTMLScriptElement
web.HTMLScriptElement _createScriptTag(String library) {
final script = web.document.createElement('script') as web.HTMLScriptElement
..type = 'text/javascript'
..charset = 'utf-8'
..async = true
Expand All @@ -42,32 +47,44 @@ HTMLScriptElement _createScriptTag(String library) {
/// Future that resolves when all load.
Future<void> _importJSLibraries(List<String> libraries) {
final loading = <Future<void>>[];
final head = document.head;
final head = web.document.head;

for (final library in libraries) {
if (!_isImported(library)) {
final scriptTag = _createScriptTag(library);
head!.appendChild(scriptTag);
loading.add(scriptTag.onLoad.first);
scriptTag.onError.listen((event) {
final scriptElement = event.srcElement is web.HTMLScriptElement
? event.srcElement as web.HTMLScriptElement
: null;
if (scriptElement != null) {
loading.add(
Future.error(
Exception('Error loading: ${scriptElement.src}'),
),
);
}
});
}
}

return Future.wait(loading);
}

bool _isImported(String url) {
final head = document.head!;
final head = web.document.head!;
return _isLoaded(head, url);
}

bool _isLoaded(HTMLHeadElement head, String url) {
bool _isLoaded(web.HTMLHeadElement head, String url) {
if (url.startsWith('./')) {
url = url.replaceFirst('./', '');
}
for (int i = 0; i < head.children.length; i++) {
final element = head.children.item(i)!;
if (element.instanceOfString('HTMLScriptElement')) {
if ((element as HTMLScriptElement).src.endsWith(url)) {
if ((element as web.HTMLScriptElement).src.endsWith(url)) {
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion wakelock_plus/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ flutter:
# https://flutter.dev/custom-fonts/#from-packages

assets:
- assets/no_sleep.js
- packages/wakelock_plus/assets/no_sleep.js
13 changes: 12 additions & 1 deletion wakelock_plus/test/wakelock_plus_web_plugin_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +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';

///
/// Run these tests with:
/// flutter run -d chrome test/wakelock_plus_web_plugin_test.dart
///
void main() {
group('$WakelockPlusWebPlugin', () {
setUpAll(() async {
// todo: the web tests do not work as the JS library import does not work.
// todo: the web tests do not work as the JS library import does not work when using flutter run test --platform chrome.
WakelockPlusPlatformInterface.instance = WakelockPlusWebPlugin();
});

Expand All @@ -24,16 +28,23 @@ void main() {

test('enable', () async {
await WakelockPlus.enable();
// Wait a bit for web to enable the wakelock
await Future.delayed(const Duration(milliseconds: 50));
expect(WakelockPlus.enabled, completion(isTrue));
});

test('disable', () async {
await WakelockPlus.enable();
// Wait a bit for web to enable the wakelock
await Future.delayed(const Duration(milliseconds: 50));
await WakelockPlus.disable();
expect(WakelockPlus.enabled, completion(isFalse));
});

test('toggle', () async {
await WakelockPlus.toggle(enable: true);
// Wait a bit for web to enable the wakelock
await Future.delayed(const Duration(milliseconds: 50));
expect(WakelockPlus.enabled, completion(isTrue));

await WakelockPlus.toggle(enable: false);
Expand Down
Loading