add keep screen awake setting

adds a user-controlled toggle (default on) under video settings that
controls whether wakelock is enabled during channel sessions. previously
wakelock was unconditional with no way to turn it off.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Tommy Chow 2026-03-06 23:58:32 -08:00
parent aad6b50d81
commit 04e5479acd
4 changed files with 77 additions and 3 deletions

View file

@ -124,7 +124,9 @@ abstract class ChatTabsStoreBase with Store {
required String primaryDisplayName,
}) {
// Enable wakelock once for all chat tabs
WakelockPlus.enable();
if (settingsStore.keepScreenAwake) {
WakelockPlus.enable();
}
// Initialize with the primary channel tab
_addPrimaryTab(

View file

@ -65,6 +65,7 @@ abstract class _SettingsStoreBase with Store {
static const defaultShowVideo = true;
static const defaultDefaultToHighestQuality = false;
static const defaultUseTextureRendering = true;
static const defaultKeepScreenAwake = true;
// Overlay defaults
static const defaultShowOverlay = true;
@ -84,6 +85,10 @@ abstract class _SettingsStoreBase with Store {
@observable
var useTextureRendering = defaultUseTextureRendering;
@JsonKey(defaultValue: defaultKeepScreenAwake)
@observable
var keepScreenAwake = defaultKeepScreenAwake;
// Overlay options
@JsonKey(defaultValue: defaultShowOverlay)
@observable
@ -102,6 +107,7 @@ abstract class _SettingsStoreBase with Store {
showVideo = defaultShowVideo;
defaultToHighestQuality = defaultDefaultToHighestQuality;
useTextureRendering = defaultUseTextureRendering;
keepScreenAwake = defaultKeepScreenAwake;
showOverlay = defaultShowOverlay;
toggleableOverlay = defaultToggleableOverlay;
@ -208,6 +214,14 @@ abstract class _SettingsStoreBase with Store {
@observable
var chatDelay = defaultChatDelay;
@JsonKey(includeFromJson: false, includeToJson: false)
@observable
var syncedChatDelay = defaultChatDelay;
@computed
double get effectiveChatDelay =>
autoSyncChatDelay ? syncedChatDelay : chatDelay;
// Alert options
@JsonKey(defaultValue: defaultHighlightFirstTimeChatter)
@observable
@ -313,6 +327,7 @@ abstract class _SettingsStoreBase with Store {
autoSyncChatDelay = defaultAutoSyncChatDelay;
chatDelay = defaultChatDelay;
syncedChatDelay = defaultChatDelay;
highlightFirstTimeChatter = defaultHighlightFirstTimeChatter;
showUserNotices = defaultShowUserNotices;
@ -401,4 +416,3 @@ enum TimestampType { disabled, twelve, twentyFour }
const landscapeCutoutNames = ['None', 'Left', 'Right', 'Both'];
enum LandscapeCutoutType { none, left, right, both }

View file

@ -23,6 +23,7 @@ SettingsStore _$SettingsStoreFromJson(
..showVideo = json['showVideo'] as bool? ?? true
..defaultToHighestQuality = json['defaultToHighestQuality'] as bool? ?? false
..useTextureRendering = json['useTextureRendering'] as bool? ?? true
..keepScreenAwake = json['keepScreenAwake'] as bool? ?? true
..showOverlay = json['showOverlay'] as bool? ?? true
..toggleableOverlay = json['toggleableOverlay'] as bool? ?? false
..showLatency = json['showLatency'] as bool? ?? false
@ -100,6 +101,7 @@ Map<String, dynamic> _$SettingsStoreToJson(
'showVideo': instance.showVideo,
'defaultToHighestQuality': instance.defaultToHighestQuality,
'useTextureRendering': instance.useTextureRendering,
'keepScreenAwake': instance.keepScreenAwake,
'showOverlay': instance.showOverlay,
'toggleableOverlay': instance.toggleableOverlay,
'showLatency': instance.showLatency,
@ -166,6 +168,15 @@ const _$LandscapeCutoutTypeEnumMap = {
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers
mixin _$SettingsStore on _SettingsStoreBase, Store {
Computed<double>? _$effectiveChatDelayComputed;
@override
double get effectiveChatDelay =>
(_$effectiveChatDelayComputed ??= Computed<double>(
() => super.effectiveChatDelay,
name: '_SettingsStoreBase.effectiveChatDelay',
)).value;
late final _$themeTypeAtom = Atom(
name: '_SettingsStoreBase.themeType',
context: context,
@ -314,6 +325,24 @@ mixin _$SettingsStore on _SettingsStoreBase, Store {
});
}
late final _$keepScreenAwakeAtom = Atom(
name: '_SettingsStoreBase.keepScreenAwake',
context: context,
);
@override
bool get keepScreenAwake {
_$keepScreenAwakeAtom.reportRead();
return super.keepScreenAwake;
}
@override
set keepScreenAwake(bool value) {
_$keepScreenAwakeAtom.reportWrite(value, super.keepScreenAwake, () {
super.keepScreenAwake = value;
});
}
late final _$showOverlayAtom = Atom(
name: '_SettingsStoreBase.showOverlay',
context: context,
@ -552,6 +581,24 @@ mixin _$SettingsStore on _SettingsStoreBase, Store {
});
}
late final _$syncedChatDelayAtom = Atom(
name: '_SettingsStoreBase.syncedChatDelay',
context: context,
);
@override
double get syncedChatDelay {
_$syncedChatDelayAtom.reportRead();
return super.syncedChatDelay;
}
@override
set syncedChatDelay(double value) {
_$syncedChatDelayAtom.reportWrite(value, super.syncedChatDelay, () {
super.syncedChatDelay = value;
});
}
late final _$highlightFirstTimeChatterAtom = Atom(
name: '_SettingsStoreBase.highlightFirstTimeChatter',
context: context,
@ -1118,6 +1165,7 @@ launchUrlExternal: ${launchUrlExternal},
showVideo: ${showVideo},
defaultToHighestQuality: ${defaultToHighestQuality},
useTextureRendering: ${useTextureRendering},
keepScreenAwake: ${keepScreenAwake},
showOverlay: ${showOverlay},
toggleableOverlay: ${toggleableOverlay},
showLatency: ${showLatency},
@ -1131,6 +1179,7 @@ showChatMessageDividers: ${showChatMessageDividers},
timestampType: ${timestampType},
autoSyncChatDelay: ${autoSyncChatDelay},
chatDelay: ${chatDelay},
syncedChatDelay: ${syncedChatDelay},
highlightFirstTimeChatter: ${highlightFirstTimeChatter},
showUserNotices: ${showUserNotices},
emoteMenuButtonOnLeft: ${emoteMenuButtonOnLeft},
@ -1155,7 +1204,8 @@ matchWholeWord: ${matchWholeWord},
shareCrashLogsAndAnalytics: ${shareCrashLogsAndAnalytics},
fullScreen: ${fullScreen},
fullScreenChatOverlay: ${fullScreenChatOverlay},
pinnedChannelIds: ${pinnedChannelIds}
pinnedChannelIds: ${pinnedChannelIds},
effectiveChatDelay: ${effectiveChatDelay}
''';
}
}

View file

@ -41,6 +41,14 @@ class VideoSettings extends StatelessWidget {
onChanged: (newValue) =>
settingsStore.useTextureRendering = newValue,
),
SettingsListSwitch(
title: 'Keep screen awake',
subtitle: const Text(
'Prevents the screen from sleeping while a channel is open.',
),
value: settingsStore.keepScreenAwake,
onChanged: (newValue) => settingsStore.keepScreenAwake = newValue,
),
const SectionHeader('Overlay'),
SettingsListSwitch(
title: 'Use custom video overlay',