Skip to content

Commit b47b3ba

Browse files
authored
Merge pull request #75 from holzgeist/fix-support-non-root-base-href
fix: add support for non-root base-href
2 parents 323d058 + b91c868 commit b47b3ba

8 files changed

Lines changed: 249 additions & 143 deletions

File tree

.github/workflows/checks.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,35 @@ jobs:
455455
flutter pub get
456456
flutter build web --debug --target=./lib/main.dart
457457
458+
web_plugin_unit_test:
459+
needs: setup_matrix
460+
runs-on: ubuntu-latest
461+
timeout-minutes: 15
462+
strategy:
463+
matrix:
464+
flutter_version: ${{ fromJson(needs.setup_matrix.outputs.flutter_versions_json) }}
465+
name: Web Plugin Unit Test (${{ matrix.flutter_version }})
466+
steps:
467+
- uses: actions/checkout@v6
468+
- uses: subosito/flutter-action@v2
469+
with:
470+
flutter-version: ${{ (contains(matrix.flutter_version, '.') || contains(matrix.flutter_version, 'x')) && matrix.flutter_version || '' }}
471+
channel: ${{ (!contains(matrix.flutter_version, '.') && !contains(matrix.flutter_version, 'x')) && matrix.flutter_version || '' }}
472+
cache: true
473+
cache-key: flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }}
474+
475+
- name: Install dependencies
476+
run: flutter pub get
477+
working-directory: wakelock_plus
478+
479+
- name: Run Web Plugin Tests
480+
run: |
481+
flutter test \
482+
--platform chrome \
483+
--dart-define=WEB_PLUGIN_TESTS=true \
484+
test/wakelock_plus_web_plugin_test.dart
485+
working-directory: wakelock_plus
486+
458487
web_integration_test:
459488
needs: setup_matrix
460489
runs-on: ubuntu-latest

wakelock_plus/example/.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,9 @@
3131
.pub/
3232
/build/
3333

34-
# Web related
35-
lib/generated_plugin_registrant.dart
36-
3734
# Symbolication related
3835
app.*.symbols
3936

4037
# Obfuscation related
4138
app.*.map.json
42-
!/ios/Podfile
39+
!/ios/Podfile
Lines changed: 94 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
/*! Based On NoSleep.js v0.12.0 - git.io/vfn01 - Rich Tibbett - MIT license */
2+
3+
class PromiseCompleter {
4+
_promise;
5+
_resolve;
6+
_reject;
7+
constructor() {
8+
this._promise = new Promise((resolve, reject) => {
9+
this._resolve = resolve;
10+
this._reject = reject;
11+
});
12+
}
13+
14+
isCompleted = false;
15+
16+
get future() {
17+
return this._promise;
18+
}
19+
20+
complete(value) {
21+
this.isCompleted = true;
22+
this._resolve(value);
23+
}
24+
25+
completeError(error) {
26+
this._reject(error);
27+
}
28+
}
29+
130
var webm =
231
'data:video/webm;base64,GkXfo0AgQoaBAUL3gQFC8oEEQvOBCEKCQAR3ZWJtQoeBAkKFgQIYU4BnQI0VSalmQCgq17FAAw9CQE2AQAZ3aGFtbXlXQUAGd2hhbW15RIlACECPQAAAAAAAFlSua0AxrkAu14EBY8WBAZyBACK1nEADdW5khkAFVl9WUDglhohAA1ZQOIOBAeBABrCBCLqBCB9DtnVAIueBAKNAHIEAAIAwAQCdASoIAAgAAUAmJaQAA3AA/vz0AAA='
332
var mp4 =
@@ -26,48 +55,28 @@ function _classCallCheck(instance, Constructor) {
2655
}
2756
}
2857

29-
// Detect iOS browsers < version 10
30-
var oldIOS =
31-
typeof navigator !== 'undefined' &&
32-
parseFloat(
33-
(
34-
'' +
35-
(/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(
36-
navigator.userAgent
37-
) || [0, ''])[1]
38-
)
39-
.replace('undefined', '3_2')
40-
.replace('_', '.')
41-
.replace('_', '')
42-
) < 10 &&
43-
!window.MSStream
44-
4558
// Detect native Wake Lock API support
4659
var nativeWakeLock = 'wakeLock' in navigator
4760

4861
var NoSleep = (function () {
49-
var _releasedNative = true
50-
var _nativeRequestInProgress = false
62+
var _nativeEnabledCompleter;
63+
var _playVideoCompleter;
5164

5265
function NoSleep() {
5366
var _this = this
5467

5568
_classCallCheck(this, NoSleep)
5669

70+
this.nativeEnabled = false
5771
if (nativeWakeLock) {
5872
this._wakeLock = null
5973
var handleVisibilityChange = function handleVisibilityChange() {
60-
if (
61-
_this._wakeLock !== null &&
62-
document.visibilityState === 'visible'
63-
) {
74+
if (_this._wakeLock !== null && document.visibilityState === 'visible') {
6475
_this.enable()
6576
}
6677
}
6778
document.addEventListener('visibilitychange', handleVisibilityChange)
6879
document.addEventListener('fullscreenchange', handleVisibilityChange)
69-
} else if (oldIOS) {
70-
this.noSleepTimer = null
7180
} else {
7281
// Set up no sleep video element
7382
this.noSleepVideo = document.createElement('video')
@@ -106,90 +115,92 @@ var NoSleep = (function () {
106115
},
107116
{
108117
key: 'enable',
109-
value: function enable() {
118+
value: async function enable() {
110119
var _this2 = this
111120

112121
if (nativeWakeLock) {
113-
_nativeRequestInProgress = true
122+
// Disable any previously held wakelocks.
123+
await this.disable()
124+
if (_nativeEnabledCompleter == null) {
125+
_nativeEnabledCompleter = new PromiseCompleter()
126+
}
114127
navigator.wakeLock
115128
.request('screen')
116129
.then(function (wakeLock) {
117-
_releasedNative = false
118-
_nativeRequestInProgress = false
119-
120130
_this2._wakeLock = wakeLock
131+
_this2.nativeEnabled = true
132+
133+
// We now have a wakelock. Notify all of the existing callers.
121134
_this2._wakeLock.addEventListener('release', function () {
122-
_releasedNative = true
135+
_this2.nativeEnabled = false
123136
_this2._wakeLock = null
124137
})
138+
139+
_nativeEnabledCompleter.complete()
140+
_nativeEnabledCompleter = null
125141
})
126142
.catch(function (err) {
127-
_nativeRequestInProgress = false
128-
console.error(err.name + ', ' + err.message)
143+
_this2.nativeEnabled = false
144+
var errorMessage = err.name + ', ' + err.message
145+
_nativeEnabledCompleter.completeError(errorMessage)
146+
_nativeEnabledCompleter = null
129147
})
130-
} else if (oldIOS) {
131-
this.disable()
132-
console.warn(
133-
'\n NoSleep enabled for older iOS devices. This can interrupt\n active or long-running network requests from completing successfully.\n See https://github.com/richtr/NoSleep.js/issues/15 for more details.\n '
134-
)
135-
this.noSleepTimer = window.setInterval(function () {
136-
if (!document.hidden) {
137-
window.location.href = window.location.href.split('#')[0]
138-
window.setTimeout(window.stop, 0)
139-
}
140-
}, 15000)
148+
// We then wait for screen to be made available.
149+
return _nativeEnabledCompleter.future
141150
} else {
142-
this.noSleepVideo.play()
151+
if (_playVideoCompleter == null) {
152+
_playVideoCompleter = new PromiseCompleter()
153+
}
154+
var playPromise = this.noSleepVideo.play()
155+
playPromise.then(function (res) {
156+
_playVideoCompleter.complete()
157+
_playVideoCompleter = null
158+
}).catch(function (err) {
159+
var errorMessage = err.name + ', ' + err.message
160+
_playVideoCompleter.completeError(errorMessage)
161+
_playVideoCompleter = null
162+
});
163+
return _playVideoCompleter.future
143164
}
144165
},
145166
},
146167
{
147168
key: 'disable',
148-
value: function disable() {
169+
value: async function disable() {
149170
if (nativeWakeLock) {
171+
// If we're still trying to enable the wakelock, wait for it to be enabled
172+
if (_nativeEnabledCompleter != null) {
173+
await _nativeEnabledCompleter.future
174+
}
150175
if (this._wakeLock != null) {
151-
_releasedNative = true
176+
this.nativeEnabled = false
152177
this._wakeLock.release()
153178
}
154179

155180
this._wakeLock = null
156-
} else if (oldIOS) {
157-
if (this.noSleepTimer) {
158-
console.warn(
159-
'\n NoSleep now disabled for older iOS devices.\n '
160-
)
161-
window.clearInterval(this.noSleepTimer)
162-
this.noSleepTimer = null
163-
}
164181
} else {
182+
if (_playVideoCompleter != null) {
183+
await _playVideoCompleter.future
184+
}
165185
this.noSleepVideo.pause()
166186
}
187+
return Promise.resolve();
167188
},
168189
},
169190
{
170-
key: 'enabled',
171-
value: async function enabled() {
191+
key: 'isEnabled',
192+
value: async function isEnabled() {
172193
if (nativeWakeLock) {
173-
if (_nativeRequestInProgress == true) {
174-
// Wait until the request is done.
175-
while (true) {
176-
// Wait for 42 milliseconds.
177-
await new Promise((resolve, reject) => setTimeout(resolve, 42))
178-
if (_nativeRequestInProgress == false) {
179-
break
180-
}
181-
}
182-
}
183-
184-
// todo: use WakeLockSentinel.released when that is available (https://developer.mozilla.org/en-US/docs/Web/API/WakeLockSentinel/released)
185-
if (_releasedNative != false) {
186-
return false
194+
// If we're still trying to enable the wakelock, wait for it to be enabled
195+
if (_nativeEnabledCompleter != null) {
196+
await _nativeEnabledCompleter.future
187197
}
188198

189-
return true
190-
} else if (oldIOS) {
191-
return this.noSleepTimer != null
199+
return this.nativeEnabled
192200
} else {
201+
if (_playVideoCompleter != null) {
202+
await _playVideoCompleter.future
203+
}
193204
if (this.noSleepVideo == undefined) {
194205
return false
195206
}
@@ -208,17 +219,22 @@ var noSleep = new NoSleep()
208219
var Wakelock = {
209220
enabled: async function () {
210221
try {
211-
return noSleep.enabled()
222+
return noSleep.isEnabled()
212223
} catch (e) {
213224
return false
214225
}
215226
},
216227
toggle: async function (enable) {
217-
if (enable) {
218-
noSleep.enable()
219-
} else {
220-
noSleep.disable()
228+
try {
229+
if (enable) {
230+
await noSleep.enable()
231+
} else {
232+
await noSleep.disable()
233+
}
234+
} catch (e) {
235+
return Promise.reject(e);
221236
}
237+
return Promise.resolve()
222238
},
223239
}
224240

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import 'dart:async';
2-
import 'dart:js_interop';
32

43
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
5-
import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interface.dart';
64
import 'package:wakelock_plus/src/web_impl/import_js_library.dart';
75
import 'package:wakelock_plus/src/web_impl/js_wakelock.dart'
86
as wakelock_plus_web;
7+
import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interface.dart';
98

109
/// The web implementation of the [WakelockPlatformInterface].
1110
///
@@ -14,45 +13,37 @@ class WakelockPlusWebPlugin extends WakelockPlusPlatformInterface {
1413
/// Registers [WakelockPlusWebPlugin] as the default instance of the
1514
/// [WakelockPlatformInterface].
1615
static void registerWith(Registrar registrar) {
17-
// Import a version of `NoSleep.js` that was adjusted for the wakelock
18-
// plugin.
19-
_jsLoaded = importJsLibrary(
16+
WakelockPlusPlatformInterface.instance = WakelockPlusWebPlugin();
17+
}
18+
19+
// The future that signals when the JS is loaded.
20+
// This needs to be `await`ed before accessing any methods of the
21+
// JS-interop layer.
22+
Future<void>? _jsLoaded;
23+
24+
//
25+
// Lazily imports the JS library once, then awaits to ensure that
26+
// it's loaded into the DOM.
27+
//
28+
Future<void> _ensureJsLoaded() async {
29+
_jsLoaded ??= importJsLibrary(
2030
url: 'assets/no_sleep.js',
2131
flutterPluginName: 'wakelock_plus',
2232
);
23-
24-
WakelockPlusPlatformInterface.instance = WakelockPlusWebPlugin();
33+
return _jsLoaded;
2534
}
2635

27-
// The future that resolves when the JS library is loaded.
28-
static late Future<void> _jsLoaded;
29-
3036
@override
3137
Future<void> toggle({required bool enable}) async {
3238
// Make sure the JS library is loaded before calling it.
33-
await _jsLoaded;
34-
35-
wakelock_plus_web.toggle(enable);
39+
await _ensureJsLoaded();
40+
await wakelock_plus_web.toggle(enable);
3641
}
3742

3843
@override
3944
Future<bool> get enabled async {
4045
// Make sure the JS library is loaded before calling it.
41-
await _jsLoaded;
42-
43-
final completer = Completer<bool>();
44-
45-
wakelock_plus_web.enabled().toDart.then(
46-
// onResolve
47-
(value) {
48-
completer.complete(value.toDart);
49-
},
50-
// onReject
51-
onError: (error) {
52-
completer.completeError(error);
53-
},
54-
);
55-
56-
return completer.future;
46+
await _ensureJsLoaded();
47+
return wakelock_plus_web.enabled();
5748
}
5849
}

0 commit comments

Comments
 (0)