From 8b7f0a3d2c660f2b80aa9ecbd6d41bc005a7b373 Mon Sep 17 00:00:00 2001 From: Strycher Date: Sat, 18 Jul 2026 02:13:40 -0400 Subject: [PATCH] feat(#269): keep-screen-awake setting Adds a KeepScreenAwake controller that holds a wakelock_plus lock while the setting is on and the app is foregrounded, releasing on background, on toggle off, and on dispose. Toggle lives in App Settings > Battery (power tradeoff), defaults OFF, persisted as keep_screen_awake. Strings added for all 18 locales. Co-Authored-By: Claude Opus 4.8 --- lib/l10n/app_bg.arb | 2 + lib/l10n/app_de.arb | 2 + lib/l10n/app_en.arb | 2 + lib/l10n/app_es.arb | 2 + lib/l10n/app_fr.arb | 2 + lib/l10n/app_hu.arb | 2 + lib/l10n/app_it.arb | 2 + lib/l10n/app_ja.arb | 2 + lib/l10n/app_ko.arb | 2 + lib/l10n/app_localizations.dart | 12 +++ lib/l10n/app_localizations_bg.dart | 7 ++ lib/l10n/app_localizations_de.dart | 7 ++ lib/l10n/app_localizations_en.dart | 7 ++ lib/l10n/app_localizations_es.dart | 7 ++ lib/l10n/app_localizations_fr.dart | 7 ++ lib/l10n/app_localizations_hu.dart | 7 ++ lib/l10n/app_localizations_it.dart | 7 ++ lib/l10n/app_localizations_ja.dart | 7 ++ lib/l10n/app_localizations_ko.dart | 7 ++ lib/l10n/app_localizations_nl.dart | 7 ++ lib/l10n/app_localizations_pl.dart | 7 ++ lib/l10n/app_localizations_pt.dart | 7 ++ lib/l10n/app_localizations_ru.dart | 7 ++ lib/l10n/app_localizations_sk.dart | 7 ++ lib/l10n/app_localizations_sl.dart | 7 ++ lib/l10n/app_localizations_sv.dart | 7 ++ lib/l10n/app_localizations_uk.dart | 7 ++ lib/l10n/app_localizations_zh.dart | 6 ++ lib/l10n/app_nl.arb | 2 + lib/l10n/app_pl.arb | 2 + lib/l10n/app_pt.arb | 2 + lib/l10n/app_ru.arb | 2 + lib/l10n/app_sk.arb | 2 + lib/l10n/app_sl.arb | 2 + lib/l10n/app_sv.arb | 2 + lib/l10n/app_uk.arb | 2 + lib/l10n/app_zh.arb | 2 + lib/main.dart | 11 ++- lib/models/app_settings.dart | 6 ++ lib/screens/settings/app_settings_view.dart | 14 ++++ lib/services/app_settings_service.dart | 4 + lib/widgets/keep_screen_awake.dart | 80 +++++++++++++++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.yaml | 1 + 44 files changed, 287 insertions(+), 4 deletions(-) create mode 100644 lib/widgets/keep_screen_awake.dart diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index 69f5e5f..16021f0 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3.0-4.2V)", "appSettings_batteryLifepo4": "Литиево желязо фосфат (2.6-3.65V)", "appSettings_batteryLipo": "Литиев полимер (3.0-4.2V)", + "appSettings_keepScreenAwake": "Поддържане на екрана включен", + "appSettings_keepScreenAwakeSubtitle": "Екранът няма да изгасва, докато приложението е отворено. Изразходва повече батерия.", "appSettings_mapDisplay": "Карта за показване", "appSettings_showRepeaters": "Показване на повторители", "appSettings_showRepeatersSubtitle": "Показване на възпроизвеждащи се възли на картата", diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index ded3337..2d8fdfe 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0–4,2 V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6–3,65 V)", "appSettings_batteryLipo": "LiPo (3,0–4,2V)", + "appSettings_keepScreenAwake": "Bildschirm anlassen", + "appSettings_keepScreenAwakeSubtitle": "Verhindert, dass sich das Display ausschaltet, während die App geöffnet ist. Verbraucht mehr Akku.", "appSettings_mapDisplay": "Kartendarstellung", "appSettings_showRepeaters": "Zeige Repeater", "appSettings_showRepeatersSubtitle": "Zeige Repeater-Knoten auf der Karte an", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 287539e..078d7c0 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -350,6 +350,8 @@ "appSettings_batteryNmc": "18650 NMC (3.0-4.2V)", "appSettings_batteryLifepo4": "LiFePO4 (2.6-3.65V)", "appSettings_batteryLipo": "LiPo (3.0-4.2V)", + "appSettings_keepScreenAwake": "Keep screen awake", + "appSettings_keepScreenAwakeSubtitle": "Prevent the display from sleeping while the app is open. Uses more battery.", "appSettings_mapDisplay": "Map Display", "appSettings_showRepeaters": "Show Repeaters", "appSettings_showRepeatersSubtitle": "Display repeater nodes on the map", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 85e6bf1..06c8c6a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2 V)", "appSettings_batteryLifepo4": "LiFePO4 (2.6-3.65 V)", "appSettings_batteryLipo": "LiPo (3.0-4.2V)", + "appSettings_keepScreenAwake": "Mantener la pantalla encendida", + "appSettings_keepScreenAwakeSubtitle": "Evita que la pantalla se apague mientras la aplicación está abierta. Consume más batería.", "appSettings_mapDisplay": "Visualización del Mapa", "appSettings_showRepeaters": "Mostrar Repetidores", "appSettings_showRepeatersSubtitle": "Mostrar nodos de repetidor en el mapa", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 72c5506..50d5a23 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6-3,65V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Garder l'écran allumé", + "appSettings_keepScreenAwakeSubtitle": "Empêche l'écran de s'éteindre lorsque l'application est ouverte. Consomme plus de batterie.", "appSettings_mapDisplay": "Affichage de la carte", "appSettings_showRepeaters": "Afficher les répéteurs", "appSettings_showRepeatersSubtitle": "Afficher les nœuds répéteurs sur la carte", diff --git a/lib/l10n/app_hu.arb b/lib/l10n/app_hu.arb index 397ec99..1e09f62 100644 --- a/lib/l10n/app_hu.arb +++ b/lib/l10n/app_hu.arb @@ -308,6 +308,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2 V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6–3,65 V)", "appSettings_batteryLipo": "LiPo (3,0-4,2 V)", + "appSettings_keepScreenAwake": "Képernyő ébren tartása", + "appSettings_keepScreenAwakeSubtitle": "Megakadályozza a képernyő elalvását, amíg az alkalmazás nyitva van. Több akkumulátort fogyaszt.", "appSettings_mapDisplay": "Térkép megjelenítése", "appSettings_showRepeaters": "Megismétlés", "appSettings_showRepeatersSubtitle": "A térképen megjelenítsük a repeater-eket.", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 7b2d226..ebe1e3f 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6-3,65V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Mantieni lo schermo acceso", + "appSettings_keepScreenAwakeSubtitle": "Impedisce allo schermo di spegnersi mentre l'app è aperta. Consuma più batteria.", "appSettings_mapDisplay": "Visualizzazione Mappa", "appSettings_showRepeaters": "Mostra Ripetitori", "appSettings_showRepeatersSubtitle": "Mostra i nodi ripetitori sulla mappa", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index f4650d9..53644cf 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -308,6 +308,8 @@ "appSettings_batteryNmc": "18650型 NMC (3.0-4.2V)", "appSettings_batteryLifepo4": "LiFePO4 (2.6-3.65V)", "appSettings_batteryLipo": "LiPo (3.0-4.2V)", + "appSettings_keepScreenAwake": "画面をスリープさせない", + "appSettings_keepScreenAwakeSubtitle": "アプリを開いている間、画面が消灯しないようにします。バッテリーの消費が増えます。", "appSettings_mapDisplay": "地図の表示", "appSettings_showRepeaters": "繰り返し再生機能", "appSettings_showRepeatersSubtitle": "地図上にリピーターノードを表示する", diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index 34984c9..8faa855 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -308,6 +308,8 @@ "appSettings_batteryNmc": "18650 NMC (3.0-4.2V)", "appSettings_batteryLifepo4": "LiFePO4 (2.6-3.65V)", "appSettings_batteryLipo": "리튬 폴리머 (3.0-4.2V)", + "appSettings_keepScreenAwake": "화면 켜짐 유지", + "appSettings_keepScreenAwakeSubtitle": "앱이 열려 있는 동안 화면이 꺼지지 않도록 합니다. 배터리를 더 소모합니다.", "appSettings_mapDisplay": "지도 표시", "appSettings_showRepeaters": "반복 기능 표시", "appSettings_showRepeatersSubtitle": "지도에 반복자 노드를 표시", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index f39a9d4..083f220 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1714,6 +1714,18 @@ abstract class AppLocalizations { /// **'LiPo (3.0-4.2V)'** String get appSettings_batteryLipo; + /// No description provided for @appSettings_keepScreenAwake. + /// + /// In en, this message translates to: + /// **'Keep screen awake'** + String get appSettings_keepScreenAwake; + + /// No description provided for @appSettings_keepScreenAwakeSubtitle. + /// + /// In en, this message translates to: + /// **'Prevent the display from sleeping while the app is open. Uses more battery.'** + String get appSettings_keepScreenAwakeSubtitle; + /// No description provided for @appSettings_mapDisplay. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 82ee646..f9352a0 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -895,6 +895,13 @@ class AppLocalizationsBg extends AppLocalizations { @override String get appSettings_batteryLipo => 'Литиев полимер (3.0-4.2V)'; + @override + String get appSettings_keepScreenAwake => 'Поддържане на екрана включен'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Екранът няма да изгасва, докато приложението е отворено. Изразходва повече батерия.'; + @override String get appSettings_mapDisplay => 'Карта за показване'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 86d780e..54a4f13 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -891,6 +891,13 @@ class AppLocalizationsDe extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0–4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Bildschirm anlassen'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Verhindert, dass sich das Display ausschaltet, während die App geöffnet ist. Verbraucht mehr Akku.'; + @override String get appSettings_mapDisplay => 'Kartendarstellung'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 5344a2a..abbea4a 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -876,6 +876,13 @@ class AppLocalizationsEn extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3.0-4.2V)'; + @override + String get appSettings_keepScreenAwake => 'Keep screen awake'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Prevent the display from sleeping while the app is open. Uses more battery.'; + @override String get appSettings_mapDisplay => 'Map Display'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index e3c2efd..c8e9878 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -890,6 +890,13 @@ class AppLocalizationsEs extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3.0-4.2V)'; + @override + String get appSettings_keepScreenAwake => 'Mantener la pantalla encendida'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Evita que la pantalla se apague mientras la aplicación está abierta. Consume más batería.'; + @override String get appSettings_mapDisplay => 'Visualización del Mapa'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 6d46e56..7c5f46c 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -896,6 +896,13 @@ class AppLocalizationsFr extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Garder l\'écran allumé'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Empêche l\'écran de s\'éteindre lorsque l\'application est ouverte. Consomme plus de batterie.'; + @override String get appSettings_mapDisplay => 'Affichage de la carte'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index 179a37d..d63ca80 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -894,6 +894,13 @@ class AppLocalizationsHu extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2 V)'; + @override + String get appSettings_keepScreenAwake => 'Képernyő ébren tartása'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Megakadályozza a képernyő elalvását, amíg az alkalmazás nyitva van. Több akkumulátort fogyaszt.'; + @override String get appSettings_mapDisplay => 'Térkép megjelenítése'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index ce6b07c..5ef61e7 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -893,6 +893,13 @@ class AppLocalizationsIt extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Mantieni lo schermo acceso'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Impedisce allo schermo di spegnersi mentre l\'app è aperta. Consuma più batteria.'; + @override String get appSettings_mapDisplay => 'Visualizzazione Mappa'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 8bfd63c..bfd0ada 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -849,6 +849,13 @@ class AppLocalizationsJa extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3.0-4.2V)'; + @override + String get appSettings_keepScreenAwake => '画面をスリープさせない'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'アプリを開いている間、画面が消灯しないようにします。バッテリーの消費が増えます。'; + @override String get appSettings_mapDisplay => '地図の表示'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 3b9adfc..7a6fea9 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -847,6 +847,13 @@ class AppLocalizationsKo extends AppLocalizations { @override String get appSettings_batteryLipo => '리튬 폴리머 (3.0-4.2V)'; + @override + String get appSettings_keepScreenAwake => '화면 켜짐 유지'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + '앱이 열려 있는 동안 화면이 꺼지지 않도록 합니다. 배터리를 더 소모합니다.'; + @override String get appSettings_mapDisplay => '지도 표시'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index dc1c51a..e981d89 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -885,6 +885,13 @@ class AppLocalizationsNl extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Scherm aan houden'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Voorkomt dat het scherm in slaapstand gaat terwijl de app open is. Verbruikt meer batterij.'; + @override String get appSettings_mapDisplay => 'Kaartweergave'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index d6f55f8..3a990e4 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -895,6 +895,13 @@ class AppLocalizationsPl extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Nie wygaszaj ekranu'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Zapobiega wygaszaniu ekranu, gdy aplikacja jest otwarta. Zużywa więcej baterii.'; + @override String get appSettings_mapDisplay => 'Wyświetlanie mapy'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index da82f6c..146694d 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -892,6 +892,13 @@ class AppLocalizationsPt extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Manter a tela ligada'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Impede que a tela desligue enquanto o app está aberto. Consome mais bateria.'; + @override String get appSettings_mapDisplay => 'Exibição do Mapa'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 67b868d..3a1ce48 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -894,6 +894,13 @@ class AppLocalizationsRu extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3.0–4.2 В)'; + @override + String get appSettings_keepScreenAwake => 'Не выключать экран'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Экран не будет гаснуть, пока приложение открыто. Расходует больше заряда.'; + @override String get appSettings_mapDisplay => 'Отображение карты'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index cb58b24..e0c16b7 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -881,6 +881,13 @@ class AppLocalizationsSk extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Nechať obrazovku zapnutú'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Zabráni vypnutiu obrazovky, kým je aplikácia otvorená. Spotrebuje viac batérie.'; + @override String get appSettings_mapDisplay => 'Zobrazenie mapy'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index abde10d..4c258e5 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -882,6 +882,13 @@ class AppLocalizationsSl extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Ohrani zaslon prižgan'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Prepreči, da bi zaslon ugasnil, medtem ko je aplikacija odprta. Porabi več baterije.'; + @override String get appSettings_mapDisplay => 'Prikaz zemljevida'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 78c3bb4..c7b1bdb 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -876,6 +876,13 @@ class AppLocalizationsSv extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3,0-4,2V)'; + @override + String get appSettings_keepScreenAwake => 'Håll skärmen tänd'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Hindrar skärmen från att slockna medan appen är öppen. Drar mer batteri.'; + @override String get appSettings_mapDisplay => 'Kartvisning'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index dcf9578..5ec0e36 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -888,6 +888,13 @@ class AppLocalizationsUk extends AppLocalizations { @override String get appSettings_batteryLipo => 'LiPo (3.0-4.2В)'; + @override + String get appSettings_keepScreenAwake => 'Не вимикати екран'; + + @override + String get appSettings_keepScreenAwakeSubtitle => + 'Екран не гаснутиме, доки застосунок відкрито. Витрачає більше заряду.'; + @override String get appSettings_mapDisplay => 'Відображення карти'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 96de896..206f4a6 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -833,6 +833,12 @@ class AppLocalizationsZh extends AppLocalizations { @override String get appSettings_batteryLipo => '锂聚合物电池 (3.0-4.2V)'; + @override + String get appSettings_keepScreenAwake => '保持屏幕常亮'; + + @override + String get appSettings_keepScreenAwakeSubtitle => '应用打开时防止屏幕休眠。会更耗电。'; + @override String get appSettings_mapDisplay => '地图显示'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 5e115be..8a11ea1 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6-3,65V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Scherm aan houden", + "appSettings_keepScreenAwakeSubtitle": "Voorkomt dat het scherm in slaapstand gaat terwijl de app open is. Verbruikt meer batterij.", "appSettings_mapDisplay": "Kaartweergave", "appSettings_showRepeaters": "Toon Repeaters", "appSettings_showRepeatersSubtitle": "Toon repeaternodes op de kaart", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 4e0dafc..81ffcb0 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6-3,65 V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Nie wygaszaj ekranu", + "appSettings_keepScreenAwakeSubtitle": "Zapobiega wygaszaniu ekranu, gdy aplikacja jest otwarta. Zużywa więcej baterii.", "appSettings_mapDisplay": "Wyświetlanie mapy", "appSettings_showRepeaters": "Pokaż przekaźniki", "appSettings_showRepeatersSubtitle": "Wyświetl węzły przekaźników na mapie", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 32307e7..05fe50a 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6-3,65V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Manter a tela ligada", + "appSettings_keepScreenAwakeSubtitle": "Impede que a tela desligue enquanto o app está aberto. Consome mais bateria.", "appSettings_mapDisplay": "Exibição do Mapa", "appSettings_showRepeaters": "Mostrar Repetidores", "appSettings_showRepeatersSubtitle": "Exibir nós de repetidor no mapa", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 8b63b47..8fea350 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -173,6 +173,8 @@ "appSettings_batteryNmc": "18650 NMC (3.0–4.2 В)", "appSettings_batteryLifepo4": "LiFePO4 (2.6–3.65 В)", "appSettings_batteryLipo": "LiPo (3.0–4.2 В)", + "appSettings_keepScreenAwake": "Не выключать экран", + "appSettings_keepScreenAwakeSubtitle": "Экран не будет гаснуть, пока приложение открыто. Расходует больше заряда.", "appSettings_mapDisplay": "Отображение карты", "appSettings_showRepeaters": "Показывать репитеры", "appSettings_showRepeatersSubtitle": "Отображать репитеры на карте", diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 9e585e6..5892bc6 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6–3,65V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Nechať obrazovku zapnutú", + "appSettings_keepScreenAwakeSubtitle": "Zabráni vypnutiu obrazovky, kým je aplikácia otvorená. Spotrebuje viac batérie.", "appSettings_mapDisplay": "Zobrazenie mapy", "appSettings_showRepeaters": "Zobraziť opakovače", "appSettings_showRepeatersSubtitle": "Zobraziť opakujúce sa uzly na mape", diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index 533bc9e..15d6493 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6–3,65 V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Ohrani zaslon prižgan", + "appSettings_keepScreenAwakeSubtitle": "Prepreči, da bi zaslon ugasnil, medtem ko je aplikacija odprta. Porabi več baterije.", "appSettings_mapDisplay": "Prikaz zemljevida", "appSettings_showRepeaters": "Prikaži repetitorje", "appSettings_showRepeatersSubtitle": "Prikaži repetitorje na mapi", diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index 0495908..ed22b2d 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -216,6 +216,8 @@ "appSettings_batteryNmc": "18650 NMC (3,0-4,2V)", "appSettings_batteryLifepo4": "LiFePO4 (2,6–3,65V)", "appSettings_batteryLipo": "LiPo (3,0-4,2V)", + "appSettings_keepScreenAwake": "Håll skärmen tänd", + "appSettings_keepScreenAwakeSubtitle": "Hindrar skärmen från att slockna medan appen är öppen. Drar mer batteri.", "appSettings_mapDisplay": "Kartvisning", "appSettings_showRepeaters": "Visa återuppslag", "appSettings_showRepeatersSubtitle": "Visa återspelsnoder på kartan", diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index c27cb52..d3c5ec6 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -218,6 +218,8 @@ "appSettings_batteryNmc": "18650 NMC (3.0-4.2В)", "appSettings_batteryLifepo4": "LiFePO4 (2.6-3.65В)", "appSettings_batteryLipo": "LiPo (3.0-4.2В)", + "appSettings_keepScreenAwake": "Не вимикати екран", + "appSettings_keepScreenAwakeSubtitle": "Екран не гаснутиме, доки застосунок відкрито. Витрачає більше заряду.", "appSettings_mapDisplay": "Відображення карти", "appSettings_showRepeaters": "Показувати ретранслятори", "appSettings_showRepeatersSubtitle": "Відображати вузли-ретранслятори на карті", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 9bec0b2..4061b0a 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -230,6 +230,8 @@ "appSettings_batteryNmc": "18650 NMC 电池 (3.0-4.2V)", "appSettings_batteryLifepo4": "磷酸铁锂 (2.6-3.65V)", "appSettings_batteryLipo": "锂聚合物电池 (3.0-4.2V)", + "appSettings_keepScreenAwake": "保持屏幕常亮", + "appSettings_keepScreenAwakeSubtitle": "应用打开时防止屏幕休眠。会更耗电。", "appSettings_mapDisplay": "地图显示", "appSettings_showRepeaters": "显示转发节点", "appSettings_showRepeatersSubtitle": "在地图上显示转发节点", diff --git a/lib/main.dart b/lib/main.dart index 655beaf..34a3a8e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -34,6 +34,7 @@ import 'storage/drift/blob_store.dart'; import 'widgets/storage_unavailable_banner.dart'; import 'storage/prefs_manager.dart'; import 'utils/app_logger.dart'; +import 'widgets/keep_screen_awake.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -279,10 +280,12 @@ class MeshCoreApp extends StatelessWidget { NotificationService().setLocale(locale); return AnnotatedRegion( value: _systemUiOverlayStyle(context), - child: Consumer( - builder: (context, health, _) => StorageUnavailableBanner( - show: !health.available, - child: child ?? const SizedBox.shrink(), + child: KeepScreenAwake( + child: Consumer( + builder: (context, health, _) => StorageUnavailableBanner( + show: !health.available, + child: child ?? const SizedBox.shrink(), + ), ), ), ); diff --git a/lib/models/app_settings.dart b/lib/models/app_settings.dart index 782e78a..70d4222 100644 --- a/lib/models/app_settings.dart +++ b/lib/models/app_settings.dart @@ -121,6 +121,7 @@ class AppSettings { final bool mapShowMarkers; final bool mapShowGuessedLocations; final bool enableMessageTracing; + final bool keepScreenAwake; final ClockFormat clockFormat; final Map? mapCacheBounds; final int mapCacheMinZoom; @@ -198,6 +199,7 @@ class AppSettings { this.mapShowMarkers = true, this.mapShowGuessedLocations = true, this.enableMessageTracing = false, + this.keepScreenAwake = false, this.clockFormat = ClockFormat.system, this.mapCacheBounds, this.mapCacheMinZoom = 10, @@ -263,6 +265,7 @@ class AppSettings { 'map_show_markers': mapShowMarkers, 'map_show_guessed_locations': mapShowGuessedLocations, 'enable_message_tracing': enableMessageTracing, + 'keep_screen_awake': keepScreenAwake, 'clock_format': clockFormat.value, 'map_cache_bounds': mapCacheBounds, 'map_cache_min_zoom': mapCacheMinZoom, @@ -352,6 +355,7 @@ class AppSettings { mapShowGuessedLocations: json['map_show_guessed_locations'] as bool? ?? true, enableMessageTracing: json['enable_message_tracing'] as bool? ?? false, + keepScreenAwake: json['keep_screen_awake'] as bool? ?? false, clockFormat: parseClockFormat(json['clock_format']), mapCacheBounds: (json['map_cache_bounds'] as Map?)?.map( (key, value) => MapEntry(key.toString(), (value as num).toDouble()), @@ -475,6 +479,7 @@ class AppSettings { bool? mapShowMarkers, bool? mapShowGuessedLocations, bool? enableMessageTracing, + bool? keepScreenAwake, ClockFormat? clockFormat, Object? mapCacheBounds = _unset, int? mapCacheMinZoom, @@ -525,6 +530,7 @@ class AppSettings { mapShowGuessedLocations: mapShowGuessedLocations ?? this.mapShowGuessedLocations, enableMessageTracing: enableMessageTracing ?? this.enableMessageTracing, + keepScreenAwake: keepScreenAwake ?? this.keepScreenAwake, clockFormat: clockFormat ?? this.clockFormat, mapCacheBounds: mapCacheBounds == _unset ? this.mapCacheBounds diff --git a/lib/screens/settings/app_settings_view.dart b/lib/screens/settings/app_settings_view.dart index 08e61b7..5486422 100644 --- a/lib/screens/settings/app_settings_view.dart +++ b/lib/screens/settings/app_settings_view.dart @@ -557,6 +557,20 @@ class AppSettingsView extends StatelessWidget { ], ), ), + + const Divider(height: 1), + SwitchListTile( + secondary: const Icon(Icons.screen_lock_portrait_outlined), + title: Text(context.l10n.appSettings_keepScreenAwake), + subtitle: Text(context.l10n.appSettings_keepScreenAwakeSubtitle), + value: settingsService.settings.keepScreenAwake, + onChanged: (value) { + persistSetting( + context, + () => settingsService.setKeepScreenAwake(value), + ); + }, + ), ], ), ); diff --git a/lib/services/app_settings_service.dart b/lib/services/app_settings_service.dart index d0ea235..4352f41 100644 --- a/lib/services/app_settings_service.dart +++ b/lib/services/app_settings_service.dart @@ -104,6 +104,10 @@ class AppSettingsService extends ChangeNotifier { await updateSettings(_settings.copyWith(enableMessageTracing: value)); } + Future setKeepScreenAwake(bool value) async { + await updateSettings(_settings.copyWith(keepScreenAwake: value)); + } + Future setClockFormat(ClockFormat value) async { await updateSettings(_settings.copyWith(clockFormat: value)); } diff --git a/lib/widgets/keep_screen_awake.dart b/lib/widgets/keep_screen_awake.dart new file mode 100644 index 0000000..4a98167 --- /dev/null +++ b/lib/widgets/keep_screen_awake.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; + +import '../services/app_settings_service.dart'; + +/// Holds a screen wakelock while [AppSettings.keepScreenAwake] is enabled and +/// the app is foregrounded (#269). +/// +/// The lock is released when the setting is turned off, when the app leaves the +/// foreground, and on dispose — so normal display sleep resumes and the +/// background foreground-service behaviour is untouched. +class KeepScreenAwake extends StatefulWidget { + const KeepScreenAwake({super.key, required this.child}); + + final Widget child; + + @override + State createState() => _KeepScreenAwakeState(); +} + +class _KeepScreenAwakeState extends State + with WidgetsBindingObserver { + AppSettingsService? _service; + bool _foreground = true; + bool _held = false; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final service = context.read(); + if (!identical(service, _service)) { + _service?.removeListener(_sync); + _service = service..addListener(_sync); + } + _sync(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + _foreground = state == AppLifecycleState.resumed; + _sync(); + } + + /// Drives the platform wakelock toward the desired state. Failures are + /// logged and leave the tracked state released, never swallowed. + Future _sync() async { + final want = (_service?.settings.keepScreenAwake ?? false) && _foreground; + if (want == _held) return; + try { + await WakelockPlus.toggle(enable: want); + _held = want; + } catch (e) { + _held = false; + debugPrint('[KeepScreenAwake] failed to set wakelock to $want: $e'); + } + } + + @override + void dispose() { + _service?.removeListener(_sync); + WidgetsBinding.instance.removeObserver(this); + if (_held) { + WakelockPlus.disable().catchError( + (Object e) => + debugPrint('[KeepScreenAwake] failed to release on dispose: $e'), + ); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) => widget.child; +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index ffc8c59..d2ea57e 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -13,6 +13,7 @@ import share_plus import shared_preferences_foundation import sqflite_darwin import url_launcher_macos +import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterBluePlusPlugin.register(with: registry.registrar(forPlugin: "FlutterBluePlusPlugin")) @@ -23,4 +24,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/pubspec.yaml b/pubspec.yaml index 2b67d78..e4a23e8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,6 +55,7 @@ dependencies: cached_network_image: ^3.4.1 flutter_cache_manager: ^3.4.1 flutter_foreground_task: ^9.2.0 + wakelock_plus: ^1.2.8 # Keep-screen-awake setting (#269) characters: ^1.4.0 package_info_plus: ^9.0.0 mobile_scanner: ^7.1.4 # QR/barcode scanning