diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7d47cf6c..68a158b5 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -265,7 +265,7 @@ "layoutName": "Layout name", "layoutNameHint": "First floor", "layoutTypeLabel": "Layout type", - "clearLayout": "Clear {amount} devices", + "clearLayout": "Remove {amount} {amount, plural, =1{device} other{devices}}", "@clearLayout": { "placeholders": { "amount": { @@ -349,7 +349,7 @@ "toDate": "To", "today": "Today", "yesterday": "Yesterday", - "never": "never", + "never": "Never", "fromToDate": "From {from} to {to}", "@fromToDate": { "placeholders": { @@ -639,6 +639,9 @@ "initialDeviceVolume": "Initial Camera Volume", "runVideoTest": "Run Video Test", "runVideoTestDescription": "Run a video test to check the state of video playback.", + "showCameraName": "Show Camera Name", + "always": "Always", + "onHover": "On hover", "@@LOCALIZATION": {}, "dateLanguage": "Date and Language", "language": "Language", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 4f94a926..20acdae6 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -613,6 +613,9 @@ "initialDeviceVolume": "Initial Camera Volume", "runVideoTest": "Run Video Test", "runVideoTestDescription": "Run a video test to check the state of video playback.", + "showCameraName": "Show Camera Name", + "always": "Always", + "onHover": "On hover", "@@LOCALIZATION": {}, "dateLanguage": "Date et Langue", "language": "Langue", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index d5ad9911..9c52a9c1 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -639,6 +639,9 @@ "initialDeviceVolume": "Initial Camera Volume", "runVideoTest": "Run Video Test", "runVideoTestDescription": "Run a video test to check the state of video playback.", + "showCameraName": "Show Camera Name", + "always": "Always", + "onHover": "On hover", "@@LOCALIZATION": {}, "dateLanguage": "Date and Language", "language": "Language", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 36c44aee..a1b86285 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -265,7 +265,7 @@ "layoutName": "Nome do layout", "layoutNameHint": "Primeiro andar", "layoutTypeLabel": "Tipo do layout", - "clearLayout": "Limpar {amount} câmeras", + "clearLayout": "Remover {amount} {amount, plural, =1{câmera} other{câmeras}}", "@clearLayout": { "placeholders": { "amount": { @@ -639,6 +639,9 @@ "initialDeviceVolume": "Volume Inicial da Câmera", "runVideoTest": "Testar Vídeo", "runVideoTestDescription": "Teste o vídeo para verificar o estado da reprodução de vídeo.", + "showCameraName": "Show Camera Name", + "always": "Always", + "onHover": "On hover", "@@LOCALIZATION": {}, "dateLanguage": "Data e Idioma", "language": "Idioma", diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index b7f327b6..5a884e1f 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -28,6 +28,7 @@ import 'package:bluecherry_client/screens/settings/shared/options_chooser_tile.d import 'package:bluecherry_client/utils/logging.dart'; import 'package:bluecherry_client/utils/storage.dart'; import 'package:bluecherry_client/utils/video_player.dart'; +import 'package:bluecherry_client/widgets/hover_button.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -57,14 +58,36 @@ enum DisplayOn { onHover, never; - static Iterable> get options { + String locale(BuildContext context) { + final loc = AppLocalizations.of(context); + return switch (this) { + DisplayOn.always => loc.always, + DisplayOn.onHover => loc.onHover, + DisplayOn.never => loc.never, + }; + } + + static Iterable> options(BuildContext context) { return values.map>((value) { return Option( value: value, - text: value.name, + text: value.locale(context), ); }); } + + T build(T child, T never, Set states) { + if (this == DisplayOn.never) { + return never; + } else if (this == DisplayOn.always) { + return child; + } else if (this == DisplayOn.onHover) { + if (states.isHovering) return child; + return never; + } else { + throw UnimplementedError('DisplayOn $this not implemented'); + } + } } class _SettingsOption { @@ -292,11 +315,17 @@ class SettingsProvider extends UnityProvider { saveAs: (value) => value.index.toString(), ); final kShowServerNameOn = _SettingsOption( - def: DisplayOn.always, + def: DisplayOn.onHover, key: 'devices.show_server_name_on', loadFrom: (value) => DisplayOn.values[int.parse(value)], saveAs: (value) => value.index.toString(), ); + final kShowVideoStatusLabelOn = _SettingsOption( + def: DisplayOn.always, + key: 'devices.show_video_status_label_on', + loadFrom: (value) => DisplayOn.values[int.parse(value)], + saveAs: (value) => value.index.toString(), + ); // Downloads final kDownloadOnMobileData = _SettingsOption( @@ -545,6 +574,7 @@ class SettingsProvider extends UnityProvider { kInitialDevicesVolume, kShowCameraNameOn, kShowServerNameOn, + kShowVideoStatusLabelOn, kDownloadOnMobileData, kChooseLocationEveryTime, kAllowAppCloseWhenDownloading, diff --git a/lib/screens/layouts/desktop/viewport.dart b/lib/screens/layouts/desktop/viewport.dart index 2866a001..a37589ad 100644 --- a/lib/screens/layouts/desktop/viewport.dart +++ b/lib/screens/layouts/desktop/viewport.dart @@ -185,13 +185,17 @@ class _DesktopTileViewportState extends State { ), child: RichText( text: TextSpan( - text: widget.device.name, style: theme.textTheme.labelLarge?.copyWith( color: Colors.white, shadows: outlinedText(), ), children: [ - if (states.isHovering) + settings.kShowCameraNameOn.value.build( + TextSpan(text: widget.device.name), + const TextSpan(), + states, + ), + settings.kShowServerNameOn.value.build( TextSpan( text: '\n' '${widget.device.externalData?.rackName ?? widget.device.server.name}', @@ -200,6 +204,9 @@ class _DesktopTileViewportState extends State { shadows: outlinedText(), ), ), + const TextSpan(), + states, + ), if (states.isHovering && showDebugInfo) TextSpan( text: @@ -307,13 +314,20 @@ class _DesktopTileViewportState extends State { const Spacer(), if (states.isHovering) reloadButton, ], - Padding( - padding: const EdgeInsetsDirectional.only( - start: 6.0, - end: 6.0, - bottom: 6.0, + settings.kShowVideoStatusLabelOn.value.build( + Padding( + padding: const EdgeInsetsDirectional.only( + start: 6.0, + end: 6.0, + bottom: 6.0, + ), + child: VideoStatusLabel( + video: video, + device: widget.device, + ), ), - child: VideoStatusLabel(video: video, device: widget.device), + const SizedBox.shrink(), + states, ), ]), ), diff --git a/lib/screens/settings/server_and_devices.dart b/lib/screens/settings/server_and_devices.dart index 46ab6443..2955d996 100644 --- a/lib/screens/settings/server_and_devices.dart +++ b/lib/screens/settings/server_and_devices.dart @@ -18,6 +18,7 @@ */ import 'package:bluecherry_client/models/device.dart'; +import 'package:bluecherry_client/models/server.dart'; import 'package:bluecherry_client/providers/settings_provider.dart'; import 'package:bluecherry_client/screens/layouts/desktop/viewport.dart'; import 'package:bluecherry_client/screens/layouts/video_status_label.dart'; @@ -410,7 +411,8 @@ class _DevicesSettingsState extends State { controller: _testPlayer, device: Device.dump( name: 'Camera Viewport', - ), + id: 1, + )..server = Server.dump(name: 'Server Name'), onFitChanged: (_) {}, showDebugInfo: true, ), @@ -421,16 +423,23 @@ class _DevicesSettingsState extends State { title: 'Show Camera Name', icon: Icons.camera_outlined, value: settings.kShowCameraNameOn.value, - values: DisplayOn.options, + values: DisplayOn.options(context), onChanged: (v) => settings.kShowCameraNameOn.value = v, ), OptionsChooserTile( title: 'Show Server Name', icon: Icons.dvr, value: settings.kShowServerNameOn.value, - values: DisplayOn.options, + values: DisplayOn.options(context), onChanged: (v) => settings.kShowServerNameOn.value = v, ), + OptionsChooserTile( + title: 'Show Video Status Label', + icon: Icons.dvr, + value: settings.kShowVideoStatusLabelOn.value, + values: DisplayOn.options(context), + onChanged: (v) => settings.kShowVideoStatusLabelOn.value = v, + ), const SizedBox(height: 20.0), ], ], diff --git a/lib/widgets/hover_button.dart b/lib/widgets/hover_button.dart index bc4ac2ae..f12fc57a 100644 --- a/lib/widgets/hover_button.dart +++ b/lib/widgets/hover_button.dart @@ -170,6 +170,10 @@ class HoverButton extends StatefulWidget { static HoverButtonState of(BuildContext context) { return context.findAncestorStateOfType()!; } + + static HoverButtonState? maybeOf(BuildContext context) { + return context.findAncestorStateOfType(); + } } class HoverButtonState extends State {