Skip to content

Commit 0c1965b

Browse files
rajveermalviyagnprice
authored andcommitted
lightbox: Toggle wakelock while video is playing
Fixes: #763
1 parent ea53a0b commit 0c1965b

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

lib/model/binding.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
77
import 'package:image_picker/image_picker.dart' as image_picker;
88
import 'package:package_info_plus/package_info_plus.dart' as package_info_plus;
99
import 'package:url_launcher/url_launcher.dart' as url_launcher;
10+
import 'package:wakelock_plus/wakelock_plus.dart' as wakelock_plus;
1011

1112
import '../host/android_notifications.dart';
1213
import '../log.dart';
@@ -174,6 +175,11 @@ abstract class ZulipBinding {
174175
required image_picker.ImageSource source,
175176
bool requestFullMetadata,
176177
});
178+
179+
/// Enables or disables screen wakelock, via package:wakelock_plus.
180+
///
181+
/// This wraps [wakelock_plus.WakelockPlus.toggle].
182+
Future<void> toggleWakelock({required bool enable});
177183
}
178184

179185
/// Like [device_info_plus.BaseDeviceInfo], but without things we don't use.
@@ -433,4 +439,9 @@ class LiveZulipBinding extends ZulipBinding {
433439
return image_picker.ImagePicker()
434440
.pickImage(source: source, requestFullMetadata: requestFullMetadata);
435441
}
442+
443+
@override
444+
Future<void> toggleWakelock({required bool enable}) async {
445+
return wakelock_plus.WakelockPlus.toggle(enable: enable);
446+
}
436447
}

lib/widgets/lightbox.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:video_player/video_player.dart';
88
import '../api/core.dart';
99
import '../api/model/model.dart';
1010
import '../log.dart';
11+
import '../model/binding.dart';
1112
import 'content.dart';
1213
import 'dialog.dart';
1314
import 'page.dart';
@@ -492,11 +493,24 @@ class _VideoLightboxPageState extends State<VideoLightboxPage> with PerAccountSt
492493
_controller?.removeListener(_handleVideoControllerUpdate);
493494
_controller?.dispose();
494495
_controller = null;
496+
// The VideoController doesn't emit a pause event
497+
// while disposing, so disable the wakelock here
498+
// explicitly.
499+
ZulipBinding.instance.toggleWakelock(enable: false);
495500
super.dispose();
496501
}
497502

498503
void _handleVideoControllerUpdate() {
499504
setState(() {});
505+
_updateWakelock();
506+
}
507+
508+
Future<void> _updateWakelock() async {
509+
if (_controller!.value.isPlaying) {
510+
await ZulipBinding.instance.toggleWakelock(enable: true);
511+
} else {
512+
await ZulipBinding.instance.toggleWakelock(enable: false);
513+
}
500514
}
501515

502516
Widget? _buildBottomAppBar(BuildContext context, Color color, double elevation) {

test/model/binding.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class TestZulipBinding extends ZulipBinding {
7474
_resetNotifications();
7575
_resetPickFiles();
7676
_resetPickImage();
77+
_resetWakelock();
7778
}
7879

7980
/// The current global store offered to a [GlobalStoreWidget].
@@ -367,6 +368,20 @@ class TestZulipBinding extends ZulipBinding {
367368
(_pickImageCalls ??= []).add((source: source, requestFullMetadata: requestFullMetadata));
368369
return pickImageResult;
369370
}
371+
372+
/// Returns the current status of wakelock, which can be
373+
/// changed via [toggleWakelock].
374+
bool get wakelockEnabled => _wakelockEnabled;
375+
bool _wakelockEnabled = false;
376+
377+
void _resetWakelock() {
378+
_wakelockEnabled = false;
379+
}
380+
381+
@override
382+
Future<void> toggleWakelock({required bool enable}) async {
383+
_wakelockEnabled = enable;
384+
}
370385
}
371386

372387
class FakeFirebaseMessaging extends Fake implements FirebaseMessaging {

test/widgets/lightbox_test.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,35 @@ void main() {
409409
expectedMessage: zulipLocalizations.errorVideoPlayerFailed)));
410410
});
411411

412+
testWidgets('toggles wakelock when playing state changes', (tester) async {
413+
await setupPage(tester, videoSrc: Uri.parse(kTestVideoUrl));
414+
check(platform.isPlaying).isTrue();
415+
check(TestZulipBinding.instance.wakelockEnabled).isTrue();
416+
417+
await tester.tap(find.byIcon(Icons.pause_circle_rounded));
418+
check(platform.isPlaying).isFalse();
419+
check(TestZulipBinding.instance.wakelockEnabled).isFalse();
420+
421+
// re-render to update player controls
422+
await tester.pump();
423+
424+
await tester.tap(find.byIcon(Icons.play_circle_rounded));
425+
check(platform.isPlaying).isTrue();
426+
check(TestZulipBinding.instance.wakelockEnabled).isTrue();
427+
});
428+
429+
testWidgets('disables wakelock when disposed', (tester) async {
430+
await setupPage(tester, videoSrc: Uri.parse(kTestVideoUrl));
431+
check(platform.isPlaying).isTrue();
432+
check(TestZulipBinding.instance.wakelockEnabled).isTrue();
433+
434+
// Replace current page with empty container,
435+
// disposing the previous page.
436+
await tester.pumpWidget(Container());
437+
438+
check(TestZulipBinding.instance.wakelockEnabled).isFalse();
439+
});
440+
412441
testWidgets('video advances over time and stops playing when it ends', (tester) async {
413442
await setupPage(tester, videoSrc: Uri.parse(kTestVideoUrl));
414443
check(platform.isPlaying).isTrue();

0 commit comments

Comments
 (0)