Skip to content

Commit bd9d308

Browse files
authored
General app updates (#197)
2 parents f9191d5 + bf65a8a commit bd9d308

23 files changed

+446
-155
lines changed

lib/l10n/app_en.arb

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"connectAutomaticallyAtStartupDescription": "If enabled, the server will be automatically connected when the app starts.",
2222
"skip": "Skip",
2323
"cancel": "Cancel",
24+
"disabled": "Disabled",
2425
"letsGo": "Let's Go!",
2526
"finish": "Finish",
2627
"letsGoDescription": "Here's some tips on how to get started:",
@@ -61,6 +62,14 @@
6162
"noServersAvailable": "No servers available",
6263
"error": "Error",
6364
"videoError": "An error happened while trying to play the video.",
65+
"copiedToClipboard": "Copied {message} to clipboard",
66+
"@copiedToClipboard": {
67+
"placeholders": {
68+
"message": {
69+
"type": "String"
70+
}
71+
}
72+
},
6473
"ok": "OK",
6574
"retry": "Retry",
6675
"clear": "Clear",
@@ -176,9 +185,12 @@
176185
"refreshServer": "Refresh server",
177186
"refresh": "Refresh",
178187
"view": "View",
188+
"cameraRefreshPeriod": "Camera refresh period",
189+
"cameraRefreshPeriodDescription": "The interval between camera refreshes. It ensures the camera video is still valid from time to time.",
179190
"@Layouts": {},
180191
"cycle": "Cycle",
181192
"cycleTogglePeriod": "Layout cycle toggle period",
193+
"cycleTogglePeriodDescription": "The interval between layout changes when the cycle mode is enabled.",
182194
"fallbackLayoutName": "Layout {layout}",
183195
"@fallbackLayoutName": {
184196
"placeholders": {
@@ -232,6 +244,14 @@
232244
"delete": "Delete",
233245
"showInFiles": "Show in Files",
234246
"noDownloads": "You haven't downloaded anything yet :/",
247+
"nDownloadsProgress": "You have {n} downloads in progress!",
248+
"@nDownloadsProgress": {
249+
"placeholders": {
250+
"n": {
251+
"type": "int"
252+
}
253+
}
254+
},
235255
"howToDownload": "Go to the \"Events History\" screen to download events.",
236256
"downloadTitle": "{event} on {device} under server {server} at {date}",
237257
"@downloadTitle": {
@@ -317,6 +337,8 @@
317337
"systemPowerOutage": "Power Lost",
318338
"unknown": "Unknown",
319339
"close": "Close",
340+
"closeAnyway": "Close anyway",
341+
"closeWhenDone": "Close when done",
320342
"open": "Open",
321343
"collapse": "Collapse",
322344
"expand": "Expand",
@@ -416,8 +438,8 @@
416438
"@@MISC": {},
417439
"general": "General",
418440
"miscellaneous": "Miscellaneous",
419-
"wakelock": "Keep screen on",
420-
"wakelockDescription": "Keep screen on while watching live streams or recordings.",
441+
"wakelock": "Keep screen awake",
442+
"wakelockDescription": "Keep screen awake while watching live streams or recordings.",
421443
"@Snoozing": {},
422444
"snooze15": "15 minutes",
423445
"snooze30": "30 minutes",
@@ -435,6 +457,7 @@
435457
},
436458
"@Notification click": {},
437459
"notificationClickBehavior": "Notification Click Behavior",
460+
"notificationClickBehaviorDescription": "Choose what happens when you click on a notification.",
438461
"showEventsScreen": "Show events history",
439462
"@@STREAMING": {},
440463
"streamingSettings": "Streaming settings",

lib/l10n/app_fr.arb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"connectAutomaticallyAtStartupDescription": "If enabled, the app will automatically connect to the server when it starts.",
2222
"skip": "Sauter",
2323
"cancel": "Annuler",
24+
"disabled": "Disabled",
2425
"letsGo": "C'EST PARTI!",
2526
"finish": "Terminé",
2627
"letsGoDescription": "Voici quelques astuces pour bien commencer:",
@@ -57,6 +58,14 @@
5758
"noServersAvailable": "Aucun serveur disponible",
5859
"error": "Erreur",
5960
"videoError": "Une erreur est survenue lors de la lecture de la vidé.",
61+
"copiedToClipboard": "Copied {message} to clipboard",
62+
"@copiedToClipboard": {
63+
"placeholders": {
64+
"message": {
65+
"type": "String"
66+
}
67+
}
68+
},
6069
"ok": "OK",
6170
"retry": "Réessayer",
6271
"clear": "Clear",
@@ -166,9 +175,12 @@
166175
"refreshServer": "Actualiser le serveur",
167176
"refresh": "Actualiser",
168177
"view": "Vue",
178+
"cameraRefreshPeriod": "Camera refresh period",
179+
"cameraRefreshPeriodDescription": "The interval between camera refreshes. It ensures the camera video is still valid from time to time.",
169180
"@Layouts": {},
170181
"cycle": "Cycle",
171182
"cycleTogglePeriod": "Durée du cycle de basculement",
183+
"cycleTogglePeriodDescription": "The interval between layout changes when the cycle mode is enabled.",
172184
"fallbackLayoutName": "Disposition {layout}",
173185
"@fallbackLayoutName": {
174186
"placeholders": {
@@ -222,6 +234,14 @@
222234
"delete": "Supprimer",
223235
"showInFiles": "Afficher dans le dossier",
224236
"noDownloads": "Vous n'avez aucun téléchargements",
237+
"nDownloadsProgress": "You have {n} downloads in progress!",
238+
"@nDownloadsProgress": {
239+
"placeholders": {
240+
"n": {
241+
"type": "int"
242+
}
243+
}
244+
},
225245
"howToDownload": "Allez à la vue \"Navigateur d'évènements\" pour télécharger des évènements.",
226246
"downloadTitle": "{event} sur {device} du serveur {server} à {date}",
227247
"@downloadTitle": {
@@ -295,6 +315,8 @@
295315
"systemPowerOutage": "Perte de courant",
296316
"unknown": "Inconnu",
297317
"close": "Ouvert",
318+
"closeAnyway": "Close anyway",
319+
"closeWhenDone": "Close when done",
298320
"open": "Fermé",
299321
"collapse": "Réduire",
300322
"expand": "Développer",
@@ -409,6 +431,7 @@
409431
},
410432
"@Notification click": {},
411433
"notificationClickBehavior": "Action de clic sur les notifications",
434+
"notificationClickBehaviorDescription": "Choose what happens when you click on a notification.",
412435
"showEventsScreen": "Montrer le navigateur d'événements",
413436
"@@STREAMING": {},
414437
"streamingSettings": "Paramètre de diffusion",

lib/l10n/app_pl.arb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"connectAutomaticallyAtStartupDescription": "If enabled, the app will automatically connect to the server when it starts.",
2222
"skip": "Pomiń",
2323
"cancel": "Anuluj",
24+
"disabled": "Disabled",
2425
"letsGo": "Do dzieła!",
2526
"finish": "Zakończ",
2627
"letsGoDescription": "Kilka porad jak zacząć:",
@@ -61,6 +62,14 @@
6162
"noServersAvailable": "Brak dostępnych serwerów",
6263
"error": "Błąd",
6364
"videoError": "An error happened while trying to play the video.",
65+
"copiedToClipboard": "Copied {message} to clipboard",
66+
"@copiedToClipboard": {
67+
"placeholders": {
68+
"message": {
69+
"type": "String"
70+
}
71+
}
72+
},
6473
"ok": "OK",
6574
"retry": "Spróbuj ponownie",
6675
"clear": "Clear",
@@ -176,9 +185,12 @@
176185
"refreshServer": "Odśwież serwer",
177186
"refresh": "Odśwież",
178187
"view": "Widok",
188+
"cameraRefreshPeriod": "Camera refresh period",
189+
"cameraRefreshPeriodDescription": "The interval between camera refreshes. It ensures the camera video is still valid from time to time.",
179190
"@Layouts": {},
180191
"cycle": "Cykl",
181192
"cycleTogglePeriod": "Okres cyklicznego przełączania układu",
193+
"cycleTogglePeriodDescription": "The interval between layout changes when the cycle mode is enabled.",
182194
"fallbackLayoutName": "Układ {layout}",
183195
"@fallbackLayoutName": {
184196
"placeholders": {
@@ -232,6 +244,14 @@
232244
"delete": "Usuń",
233245
"showInFiles": "Pokaż w Plikach",
234246
"noDownloads": "Jeszcze niczego nie pobrano :/",
247+
"nDownloadsProgress": "You have {n} downloads in progress!",
248+
"@nDownloadsProgress": {
249+
"placeholders": {
250+
"n": {
251+
"type": "int"
252+
}
253+
}
254+
},
235255
"howToDownload": "Przejdź do ekranu \"Historii zdarzeń\" by pobrać zdarzenia.",
236256
"downloadTitle": "{event} na {device} serwer {server} o {date}",
237257
"@downloadTitle": {
@@ -317,6 +337,8 @@
317337
"systemPowerOutage": "Utrata zasilania",
318338
"unknown": "Nieznany",
319339
"close": "Zamknij",
340+
"closeAnyway": "Close anyway",
341+
"closeWhenDone": "Close when done",
320342
"open": "Otwórz",
321343
"collapse": "Zwiń",
322344
"expand": "Rozwiń",
@@ -435,6 +457,7 @@
435457
},
436458
"@Notification click": {},
437459
"notificationClickBehavior": "Zachowanie po kliknięciu na powiadomienie",
460+
"notificationClickBehaviorDescription": "Choose what happens when you click on a notification.",
438461
"showEventsScreen": "Pokaż historię zdarzeń",
439462
"@@STREAMING": {},
440463
"streamingSettings": "Streaming settings",

lib/l10n/app_pt.arb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"connectAutomaticallyAtStartupDescription": "Se ativado, o servidor será conectado automaticamente quando o aplicativo for iniciado.",
2222
"skip": "Pular",
2323
"cancel": "Cancelar",
24+
"disabled": "Desativado",
2425
"letsGo": "Vamos lá!",
2526
"finish": "Concluir",
2627
"letsGoDescription": "Aqui algumas dicas de como começar:",
@@ -61,6 +62,14 @@
6162
"noServersAvailable": "Nenhum servidor disponível.",
6263
"error": "Erro",
6364
"videoError": "Ocorreu um erro ao tentar reproduzir o vídeo.",
65+
"copiedToClipboard": "{message} foi copiado para a área de transferência.",
66+
"@copiedToClipboard": {
67+
"placeholders": {
68+
"message": {
69+
"type": "String"
70+
}
71+
}
72+
},
6473
"ok": "OK",
6574
"retry": "Tentar novamente",
6675
"clear": "Limpar",
@@ -176,9 +185,12 @@
176185
"refreshServer": "Recarregar servidor",
177186
"refresh": "Recarregar",
178187
"view": "Layouts",
188+
"cameraRefreshPeriod": "Intervalo para recarregar cameras",
189+
"cameraRefreshPeriodDescription": "O intervalo entre as atualizações da câmera. Isso garante que o vídeo da câmera ainda seja válido de tempos em tempos.",
179190
"@Layouts": {},
180191
"cycle": "Ciclo",
181192
"cycleTogglePeriod": "Duração da alternância de layouts",
193+
"cycleTogglePeriodDescription": "O intervalo entre alterações de layout quando a alternância está ativada.",
182194
"fallbackLayoutName": "Layout {layout}",
183195
"@fallbackLayoutName": {
184196
"placeholders": {
@@ -232,6 +244,14 @@
232244
"delete": "Deletar",
233245
"showInFiles": "Ver no Explorador de Arquivos",
234246
"noDownloads": "Você ainda não baixou nenhum evento :/",
247+
"nDownloadsProgress": "Você tem {n} downloads em progresso!",
248+
"@nDownloadsProgress": {
249+
"placeholders": {
250+
"n": {
251+
"type": "int"
252+
}
253+
}
254+
},
235255
"howToDownload": "Vá ao \"Histórico de Eventos\" para baixar eventos.",
236256
"downloadTitle": "{event} de {device} do servidor {server} em {date}",
237257
"@downloadTitle": {
@@ -317,6 +337,8 @@
317337
"systemPowerOutage": "Perda de energia",
318338
"unknown": "Desconhecido",
319339
"close": "Fechar",
340+
"closeAnyway": "Fechar mesmo assim",
341+
"closeWhenDone": "Fechar quando terminar",
320342
"open": "Abrir",
321343
"collapse": "Fechar",
322344
"expand": "Expandir",
@@ -435,6 +457,7 @@
435457
},
436458
"@Notification click": {},
437459
"notificationClickBehavior": "Ação ao clicar na notificação",
460+
"notificationClickBehaviorDescription": "Escolha o que acontece quando você clica em uma notificação.",
438461
"showEventsScreen": "Mostar histórico de eventos",
439462
"@@STREAMING": {},
440463
"streamingSettings": "Configurações de streaming",

lib/main.dart

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import 'package:bluecherry_client/utils/theme.dart';
4343
import 'package:bluecherry_client/utils/video_player.dart';
4444
import 'package:bluecherry_client/utils/window.dart';
4545
import 'package:bluecherry_client/widgets/desktop_buttons.dart';
46+
import 'package:bluecherry_client/widgets/downloads_manager.dart';
4647
import 'package:bluecherry_client/widgets/events/events_screen.dart';
4748
import 'package:bluecherry_client/widgets/home.dart';
4849
import 'package:bluecherry_client/widgets/multi_window/single_camera_window.dart';
@@ -59,6 +60,7 @@ import 'package:path/path.dart' as path;
5960
import 'package:permission_handler/permission_handler.dart';
6061
import 'package:provider/provider.dart';
6162
import 'package:unity_video_player/unity_video_player.dart';
63+
import 'package:window_manager/window_manager.dart';
6264

6365
final navigatorKey = GlobalKey<NavigatorState>();
6466

@@ -180,16 +182,24 @@ class UnityApp extends StatefulWidget {
180182
State<UnityApp> createState() => _UnityAppState();
181183
}
182184

183-
class _UnityAppState extends State<UnityApp> with WidgetsBindingObserver {
185+
class _UnityAppState extends State<UnityApp>
186+
with WidgetsBindingObserver, WindowListener {
184187
@override
185188
void initState() {
186189
super.initState();
187190
WidgetsBinding.instance.addObserver(this);
191+
windowManager.addListener(this);
192+
if (isDesktopPlatform) {
193+
windowManager.setPreventClose(true).then((_) {
194+
if (mounted) setState(() {});
195+
});
196+
}
188197
}
189198

190199
@override
191200
void dispose() {
192201
WidgetsBinding.instance.removeObserver(this);
202+
windowManager.removeListener(this);
193203
super.dispose();
194204
}
195205

@@ -220,6 +230,37 @@ class _UnityAppState extends State<UnityApp> with WidgetsBindingObserver {
220230
}
221231
}
222232

233+
@override
234+
Future<void> onWindowClose() async {
235+
final isPreventClose = await windowManager.isPreventClose();
236+
final context = navigatorKey.currentContext!;
237+
if (isPreventClose && mounted && context.mounted) {
238+
final downloadsManager = context.read<DownloadsManager>();
239+
if (downloadsManager.downloading.isNotEmpty || true) {
240+
final result = await showDialog<bool>(
241+
context: context,
242+
barrierDismissible: false,
243+
builder: (context) => const CloseDownloadsDialog(),
244+
);
245+
if (result == null || !result) {
246+
return;
247+
}
248+
}
249+
250+
// We ensure all the players are disposed in order to not keep the app alive
251+
// in background, wasting unecessary resources!
252+
253+
windowManager.hide();
254+
await Future.microtask(() async {
255+
for (final player in UnityVideoPlayerInterface.players.toList()) {
256+
debugPrint('Disposing player ${player.hashCode}');
257+
await player.dispose();
258+
}
259+
});
260+
windowManager.destroy();
261+
}
262+
}
263+
223264
@override
224265
Widget build(BuildContext context) {
225266
return MultiProvider(

0 commit comments

Comments
 (0)