From 4cc3d5ad1958654a833cc581026552ab96c69080 Mon Sep 17 00:00:00 2001 From: Bruno D'Luka <45696119+bdlukaa@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:10:12 -0300 Subject: [PATCH 1/3] chore: Build raspberry-pi binaries --- .github/workflows/build.yml | 27 +++++++++++++ .../unity_video_player_flutter/pubspec.yaml | 2 +- pubspec.lock | 38 ++++--------------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 44576516..f36eedc2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -322,3 +322,30 @@ jobs: bluecherry-linux-x86_64.tar.gz bluecherry-linux-x86_64.rpm token: ${{ secrets.GITHUB_TOKEN }} + + build_pi: + name: Bluecherry Raspberry Pi + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + submodules: recursive + + - name: Install Flutter + uses: subosito/flutter-action@v2.8.0 + with: + channel: "master" + # cache: true + + - name: Initiate Flutter + run: | + flutter gen-l10n + flutter pub get + flutter pub global activate flutterpi_tool + + - name: Build + run: | + flutterpi_tool build --release --cpu=pi4 + diff --git a/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml b/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml index fa3f833f..46ceff25 100644 --- a/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml +++ b/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml @@ -6,7 +6,7 @@ homepage: publish_to: "none" environment: - sdk: '>=3.3.0-149.0.dev <4.0.0' + sdk: ">=3.0.0 <4.0.0" flutter: ">=1.17.0" dependencies: diff --git a/pubspec.lock b/pubspec.lock index 81dd4979..91e9528c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -461,22 +461,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "04be76c4a4bb50f14904e64749237e541e7c7bcf7ec0b196907322ab5d2fc739" - url: "https://pub.dev" - source: hosted - version: "9.0.16" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: b06739349ec2477e943055aea30172c5c7000225f79dad4702e2ec0eda79a6ff - url: "https://pub.dev" - source: hosted - version: "1.0.5" lints: dependency: transitive description: @@ -505,10 +489,10 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.5.0" media_kit: dependency: transitive description: @@ -583,10 +567,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.10.0" msix: dependency: "direct dev" description: @@ -1147,14 +1131,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 - url: "https://pub.dev" - source: hosted - version: "13.0.0" volume_controller: dependency: transitive description: @@ -1183,10 +1159,10 @@ packages: dependency: transitive description: name: web - sha256: edc8a9573dd8c5a83a183dae1af2b6fd4131377404706ca4e5420474784906fa + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.3.0" win32: dependency: transitive description: @@ -1244,5 +1220,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0-149.0.dev <4.0.0" + dart: ">=3.2.0 <4.0.0" flutter: ">=3.16.0" From b180f6b7aafbc05ddb011c30a4dc2bced4ede98c Mon Sep 17 00:00:00 2001 From: Bruno D'Luka <45696119+bdlukaa@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:31:21 -0300 Subject: [PATCH 2/3] chore: Detect if it is running on pi as a singleton --- .github/workflows/build.yml | 4 +- lib/providers/update_provider.dart | 52 +++++++++++++++++------ lib/widgets/settings/desktop/updates.dart | 3 +- lib/widgets/settings/mobile/settings.dart | 2 +- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f36eedc2..1b257362 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -336,8 +336,8 @@ jobs: - name: Install Flutter uses: subosito/flutter-action@v2.8.0 with: - channel: "master" - # cache: true + channel: "stable" + cache: false - name: Initiate Flutter run: | diff --git a/lib/providers/update_provider.dart b/lib/providers/update_provider.dart index 6ef2158c..d1396c4d 100644 --- a/lib/providers/update_provider.dart +++ b/lib/providers/update_provider.dart @@ -72,14 +72,32 @@ class UpdateVersion { static const descriptionField = 'description'; static const publishedAtField = 'pubDate'; - static const rpm = 'rpm'; - static const deb = 'deb'; - static const tarball = 'tar.gz'; - static const appImage = 'appimage'; static const linuxDownloadFileName = 'bluecherry-linux-x86_64'; static const windowsDownloadFileName = 'bluecherry-windows-setup'; } +enum LinuxPlatform { + rpm('rpm'), + deb('deb'), + appImage('AppImage'), + tarball('tar.gz'), + pi(null); + + final String? value; + + const LinuxPlatform(this.value); + + String get name { + return switch (this) { + LinuxPlatform.deb => 'Debian', + LinuxPlatform.rpm => 'Rpm', + LinuxPlatform.appImage => 'AppImage', + LinuxPlatform.tarball => 'Tarball', + LinuxPlatform.pi || _ => 'Raspberry Pi' + }; + } +} + class UpdateManager extends UnityProvider { UpdateManager._(); @@ -205,15 +223,21 @@ class UpdateManager extends UnityProvider { /// See also: /// /// * [install], which uses this method to install the correct executable. - String? get linuxEnvironment { + static LinuxPlatform get linuxEnvironment { assert( Platform.isLinux, 'This should never be reached on non-Linux platforms.', ); - if (!const bool.hasEnvironment('linux_environment')) return null; + if (!const bool.hasEnvironment('linux_environment')) { + return LinuxPlatform.pi; + } - return const String.fromEnvironment('linux_environment'); + return LinuxPlatform.values.firstWhere( + (linux) => + linux.value == const String.fromEnvironment('linux_environment'), + orElse: () => LinuxPlatform.pi, + ); } /// Check if updates are supported on the current platform. @@ -225,8 +249,8 @@ class UpdateManager extends UnityProvider { bool get isUpdatingSupported { if (Platform.isWindows) return true; if (Platform.isLinux) { - return linuxEnvironment != null && - linuxEnvironment != UpdateVersion.appImage; + return linuxEnvironment != LinuxPlatform.appImage && + linuxEnvironment != LinuxPlatform.pi; } return false; @@ -285,7 +309,6 @@ class UpdateManager extends UnityProvider { fileName = UpdateVersion.windowsDownloadFileName; extension = '.exe'; } else if (Platform.isLinux) { - assert(linuxEnvironment != null); fileName = UpdateVersion.linuxDownloadFileName; extension = '.$linuxEnvironment'; } else { @@ -351,16 +374,17 @@ class UpdateManager extends UnityProvider { ]); } else if (Platform.isLinux) { switch (linuxEnvironment) { - case UpdateVersion.rpm: + case LinuxPlatform.rpm: Process.run('tar', ['-U', executable.path]); break; - case UpdateVersion.deb: + case LinuxPlatform.deb: Process.run('sudo', ['dpkg', '-i', executable.path]); break; - case UpdateVersion.tarball: // tarball + case LinuxPlatform.tarball: // tarball Process.run('tar', ['-i', executable.path]); break; - case UpdateVersion.appImage: + case LinuxPlatform.pi: + case LinuxPlatform.appImage: throw UnsupportedError('AppImages do not support updating from app'); default: throw UnsupportedError( diff --git a/lib/widgets/settings/desktop/updates.dart b/lib/widgets/settings/desktop/updates.dart index 9758dc62..fb4787fa 100644 --- a/lib/widgets/settings/desktop/updates.dart +++ b/lib/widgets/settings/desktop/updates.dart @@ -35,7 +35,6 @@ class UpdatesSettings extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final loc = AppLocalizations.of(context); - final update = context.watch(); return ListView(padding: DesktopSettings.verticalPadding, children: [ Padding( @@ -48,7 +47,7 @@ class UpdatesSettings extends StatelessWidget { Text( loc.runningOn(() { if (Platform.isLinux) { - return loc.linux(update.linuxEnvironment ?? ''); + return loc.linux(UpdateManager.linuxEnvironment.name); } else if (Platform.isWindows) { return loc.windows; } diff --git a/lib/widgets/settings/mobile/settings.dart b/lib/widgets/settings/mobile/settings.dart index f2a9a1ff..5f57bf4d 100644 --- a/lib/widgets/settings/mobile/settings.dart +++ b/lib/widgets/settings/mobile/settings.dart @@ -167,7 +167,7 @@ class _MobileSettingsState extends State { loc.updates, subtext: loc.runningOn(() { if (Platform.isLinux) { - return loc.linux(update.linuxEnvironment ?? ''); + return loc.linux(UpdateManager.linuxEnvironment.name); } else if (Platform.isWindows) { return loc.windows; } From 79e2d05c38b632421e6cb5d20f80d6d86d973f6c Mon Sep 17 00:00:00 2001 From: Bruno D'Luka <45696119+bdlukaa@users.noreply.github.com> Date: Tue, 2 Jan 2024 23:11:35 -0300 Subject: [PATCH 3/3] feat: Block platform code usage when embedded --- lib/main.dart | 12 ++- lib/models/layout.dart | 2 +- lib/providers/home_provider.dart | 5 ++ lib/providers/settings_provider.dart | 12 ++- lib/providers/update_provider.dart | 42 +++++---- lib/utils/methods.dart | 5 +- lib/utils/storage.dart | 89 ++++++++++--------- lib/utils/window.dart | 52 +++++++---- lib/widgets/desktop_buttons.dart | 3 +- lib/widgets/settings/mobile/settings.dart | 3 +- lib/widgets/settings/shared/update.dart | 14 +-- .../lib/unity_video_player_flutter.dart | 11 ++- 12 files changed, 155 insertions(+), 95 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d8d4651c..90278ac8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -60,6 +60,8 @@ import 'package:path/path.dart' as path; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:unity_video_player/unity_video_player.dart'; +import 'package:unity_video_player_flutter/unity_video_player_flutter.dart'; +import 'package:unity_video_player_main/unity_video_player_main.dart'; import 'package:window_manager/window_manager.dart'; final navigatorKey = GlobalKey(); @@ -80,6 +82,14 @@ Future main(List args) async { DevHttpOverrides.configureCertificates(); await UnityVideoPlayerInterface.instance.initialize(); + if (isDesktopPlatform && Platform.isLinux) { + if (UpdateManager.linuxEnvironment == LinuxPlatform.embedded) { + UnityVideoPlayerFlutterInterface.registerWith(); + } else { + UnityVideoPlayerMediaKitInterface.registerWith(); + } + } + debugPrint(UnityVideoPlayerInterface.instance.runtimeType.toString()); await configureStorage(); logging.writeLogToFile('Opening app with $args'); @@ -189,7 +199,7 @@ class _UnityAppState extends State super.initState(); WidgetsBinding.instance.addObserver(this); windowManager.addListener(this); - if (isDesktopPlatform) { + if (isDesktopPlatform && canConfigureWindow) { windowManager.setPreventClose(true).then((_) { if (mounted) setState(() {}); }); diff --git a/lib/models/layout.dart b/lib/models/layout.dart index 197182ca..515350fb 100644 --- a/lib/models/layout.dart +++ b/lib/models/layout.dart @@ -129,7 +129,7 @@ class Layout { ..processing('xml', 'version="1.0"') ..processing( 'client-version', - UpdateManager.instance.packageInfo.version, + UpdateManager.instance.packageInfo?.version ?? 'beta', ); builder.element('layout', nest: () { builder diff --git a/lib/providers/home_provider.dart b/lib/providers/home_provider.dart index 7008e512..db94db93 100644 --- a/lib/providers/home_provider.dart +++ b/lib/providers/home_provider.dart @@ -20,6 +20,7 @@ import 'package:bluecherry_client/main.dart'; import 'package:bluecherry_client/providers/server_provider.dart'; import 'package:bluecherry_client/providers/settings_provider.dart'; +import 'package:bluecherry_client/providers/update_provider.dart'; import 'package:bluecherry_client/utils/methods.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -142,6 +143,10 @@ class HomeProvider extends ChangeNotifier { } void updateWakelock(BuildContext context) { + if (UpdateManager.isEmbedded) { + // we can not access wakelock from the pi + return; + } final settings = context.read(); if (!settings.wakelockEnabled) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 865dbde9..12b656c2 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -22,6 +22,7 @@ import 'dart:io'; import 'package:bluecherry_client/providers/app_provider_interface.dart'; import 'package:bluecherry_client/providers/downloads_provider.dart'; import 'package:bluecherry_client/providers/home_provider.dart'; +import 'package:bluecherry_client/providers/update_provider.dart'; import 'package:bluecherry_client/utils/constants.dart'; import 'package:bluecherry_client/utils/storage.dart'; import 'package:bluecherry_client/utils/video_player.dart'; @@ -243,12 +244,17 @@ class SettingsProvider extends UnityProvider { } else { _themeMode = kDefaultThemeMode; } - final format = SystemDateTimeFormat(); + initializeDateFormatting(_locale.languageCode); Intl.defaultLocale = _locale.toLanguageTag(); - final systemLocale = Intl.getCurrentLocale(); - final timePattern = await format.getTimePattern(); + String? timePattern; + if (!UpdateManager.isEmbedded) { + // can not access system_date_time_format from embedded + final format = SystemDateTimeFormat(); + timePattern = await format.getTimePattern(); + } + _dateFormat = DateFormat( data[kHiveDateFormat] ?? kDefaultDateFormat, systemLocale, diff --git a/lib/providers/update_provider.dart b/lib/providers/update_provider.dart index d1396c4d..3d0ba683 100644 --- a/lib/providers/update_provider.dart +++ b/lib/providers/update_provider.dart @@ -81,7 +81,7 @@ enum LinuxPlatform { deb('deb'), appImage('AppImage'), tarball('tar.gz'), - pi(null); + embedded(null); final String? value; @@ -93,7 +93,7 @@ enum LinuxPlatform { LinuxPlatform.rpm => 'Rpm', LinuxPlatform.appImage => 'AppImage', LinuxPlatform.tarball => 'Tarball', - LinuxPlatform.pi || _ => 'Raspberry Pi' + LinuxPlatform.embedded || _ => 'Embedded' }; } } @@ -103,15 +103,13 @@ class UpdateManager extends UnityProvider { /// `late` initialized [UpdateManager] instance. static late final UpdateManager instance; - late final PackageInfo packageInfo; + late final PackageInfo? packageInfo; late String tempDir; /// The URL to the appcast file. static const appCastUrl = 'https://raw.githubusercontent.com/bluecherrydvr/unity/main/bluecherry_appcast.xml'; - /// Initializes the [UpdateManager] instance & fetches state from `async` - /// `package:hive` method-calls. Called before [runApp]. static Future ensureInitialized() async { instance = UpdateManager._(); await instance.initialize(); @@ -122,9 +120,9 @@ class UpdateManager extends UnityProvider { /// /// If false, the user is up to date with the latest version. bool get hasUpdateAvailable { - if (this.latestVersion == null) return false; + if (this.latestVersion == null || packageInfo == null) return false; - final currentVersion = Version.parse(packageInfo.version); + final currentVersion = Version.parse(packageInfo!.version); final latestVersion = Version.parse(this.latestVersion!.version); // assert( @@ -148,9 +146,14 @@ class UpdateManager extends UnityProvider { await Future.wait([ checkForUpdates(), - PackageInfo.fromPlatform().then((result) { - packageInfo = result; - }) + if (isEmbedded) + () async { + packageInfo = null; + }() + else + PackageInfo.fromPlatform().then((result) { + packageInfo = result; + }), ]); if (hasUpdateAvailable && automaticDownloads) { @@ -214,6 +217,8 @@ class UpdateManager extends UnityProvider { /// * `AppImage` /// * `tar.gz` (tarball) /// + /// Null defaults to Raspberry Pi + /// /// This means the value represent the file extension of the executable. /// /// Each Flutter executable is built with a different `linux_environment` @@ -230,27 +235,34 @@ class UpdateManager extends UnityProvider { ); if (!const bool.hasEnvironment('linux_environment')) { - return LinuxPlatform.pi; + return LinuxPlatform.embedded; } return LinuxPlatform.values.firstWhere( (linux) => linux.value == const String.fromEnvironment('linux_environment'), - orElse: () => LinuxPlatform.pi, + orElse: () => LinuxPlatform.embedded, ); } + /// Whether the current platform is embedded + static bool get isEmbedded { + return isDesktopPlatform && + Platform.isLinux && + UpdateManager.linuxEnvironment == LinuxPlatform.embedded; + } + /// Check if updates are supported on the current platform. /// /// On Windows, updates are always supported. /// /// On Linux, updates are supported if the `linux_environment` is set and it /// is not an `AppImage`. - bool get isUpdatingSupported { + static bool get isUpdatingSupported { if (Platform.isWindows) return true; if (Platform.isLinux) { return linuxEnvironment != LinuxPlatform.appImage && - linuxEnvironment != LinuxPlatform.pi; + linuxEnvironment != LinuxPlatform.embedded; } return false; @@ -383,7 +395,7 @@ class UpdateManager extends UnityProvider { case LinuxPlatform.tarball: // tarball Process.run('tar', ['-i', executable.path]); break; - case LinuxPlatform.pi: + case LinuxPlatform.embedded: case LinuxPlatform.appImage: throw UnsupportedError('AppImages do not support updating from app'); default: diff --git a/lib/utils/methods.dart b/lib/utils/methods.dart index a289ef4c..9252429f 100644 --- a/lib/utils/methods.dart +++ b/lib/utils/methods.dart @@ -19,6 +19,7 @@ import 'dart:io'; import 'package:bluecherry_client/main.dart' show navigatorKey; +import 'package:bluecherry_client/providers/update_provider.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -138,7 +139,9 @@ bool get isCupertino { /// is connected to a WiFi network, then it returns 400, otherwise it returns /// 200. Future get eventsLimit async { - final connectivityResult = await Connectivity().checkConnectivity(); + final connectivityResult = UpdateManager.isEmbedded + ? ConnectivityResult.wifi + : await Connectivity().checkConnectivity(); switch (connectivityResult) { case ConnectivityResult.wifi: diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 3582d361..12061aa2 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -19,6 +19,7 @@ import 'dart:io'; +import 'package:bluecherry_client/providers/update_provider.dart'; import 'package:bluecherry_client/utils/constants.dart'; import 'package:flutter/foundation.dart'; import 'package:hive_flutter/hive_flutter.dart'; @@ -40,47 +41,53 @@ Future configureStorage() async { desktopView = SafeLocalStorage(path.join(dir, 'desktopView.json')); updates = SafeLocalStorage(path.join(dir, 'updates.json')); - // Migrate from hive to new storage system - await Hive.initFlutter(dir); - if (await Hive.boxExists('hive')) { - final hive = await Hive.openBox('hive'); - if (hive.isEmpty) { - hive.close(); - } else { - await Future.wait([ - storage._replaceIfNotNull( - kHiveNotificationToken, hive.get(kHiveNotificationToken)), - desktopView._replaceIfNotNull( - kHiveDesktopLayouts, hive.get(kHiveDesktopLayouts)), - desktopView._replaceIfNotNull( - kHiveDesktopCurrentLayout, hive.get(kHiveDesktopCurrentLayout)), - downloads._replaceIfNotNull(kHiveDownloads, hive.get(kHiveDownloads)), - eventsPlayback._replaceIfNotNull( - kHiveEventsPlayback, hive.get(kHiveEventsPlayback)), - mobileView._replaceIfNotNull( - kHiveMobileView, hive.get(kHiveMobileView)), - mobileView._replaceIfNotNull( - kHiveMobileViewTab, hive.get(kHiveMobileViewTab)), - serversStorage._replaceIfNotNull(kHiveServers, hive.get(kHiveServers)), - settings._replaceIfNotNull(kHiveThemeMode, hive.get(kHiveThemeMode)), - settings._replaceIfNotNull(kHiveDateFormat, hive.get(kHiveDateFormat)), - settings._replaceIfNotNull(kHiveTimeFormat, hive.get(kHiveTimeFormat)), - settings._replaceIfNotNull( - kHiveSnoozedUntil, hive.get(kHiveSnoozedUntil)), - settings._replaceIfNotNull( - kHiveNotificationClickBehavior, - hive.get(kHiveNotificationClickBehavior), - ), - settings._replaceIfNotNull( - kHiveCameraViewFit, - hive.get(kHiveCameraViewFit), - ), - settings._replaceIfNotNull( - kHiveDownloadsDirectorySetting, - hive.get(kHiveDownloadsDirectorySetting), - ), - ]); - await Hive.deleteBoxFromDisk('hive'); + if (!UpdateManager.isEmbedded) { + // Migrate from hive to new storage system + // TODO(bdlukaa): remove this legacy code when stable is released + await Hive.initFlutter(dir); + if (await Hive.boxExists('hive')) { + final hive = await Hive.openBox('hive'); + if (hive.isEmpty) { + hive.close(); + } else { + await Future.wait([ + storage._replaceIfNotNull( + kHiveNotificationToken, hive.get(kHiveNotificationToken)), + desktopView._replaceIfNotNull( + kHiveDesktopLayouts, hive.get(kHiveDesktopLayouts)), + desktopView._replaceIfNotNull( + kHiveDesktopCurrentLayout, hive.get(kHiveDesktopCurrentLayout)), + downloads._replaceIfNotNull(kHiveDownloads, hive.get(kHiveDownloads)), + eventsPlayback._replaceIfNotNull( + kHiveEventsPlayback, hive.get(kHiveEventsPlayback)), + mobileView._replaceIfNotNull( + kHiveMobileView, hive.get(kHiveMobileView)), + mobileView._replaceIfNotNull( + kHiveMobileViewTab, hive.get(kHiveMobileViewTab)), + serversStorage._replaceIfNotNull( + kHiveServers, hive.get(kHiveServers)), + settings._replaceIfNotNull(kHiveThemeMode, hive.get(kHiveThemeMode)), + settings._replaceIfNotNull( + kHiveDateFormat, hive.get(kHiveDateFormat)), + settings._replaceIfNotNull( + kHiveTimeFormat, hive.get(kHiveTimeFormat)), + settings._replaceIfNotNull( + kHiveSnoozedUntil, hive.get(kHiveSnoozedUntil)), + settings._replaceIfNotNull( + kHiveNotificationClickBehavior, + hive.get(kHiveNotificationClickBehavior), + ), + settings._replaceIfNotNull( + kHiveCameraViewFit, + hive.get(kHiveCameraViewFit), + ), + settings._replaceIfNotNull( + kHiveDownloadsDirectorySetting, + hive.get(kHiveDownloadsDirectorySetting), + ), + ]); + await Hive.deleteBoxFromDisk('hive'); + } } } } diff --git a/lib/utils/window.dart b/lib/utils/window.dart index 95d9d785..c0fdbc2a 100644 --- a/lib/utils/window.dart +++ b/lib/utils/window.dart @@ -23,6 +23,7 @@ import 'dart:io'; import 'package:bluecherry_client/models/device.dart'; import 'package:bluecherry_client/models/layout.dart'; import 'package:bluecherry_client/providers/settings_provider.dart'; +import 'package:bluecherry_client/providers/update_provider.dart'; import 'package:bluecherry_client/utils/methods.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -32,24 +33,37 @@ import 'package:window_manager/window_manager.dart'; /// The initial size of the window const kInitialWindowSize = Size(1066, 645); +bool get canConfigureWindow { + if (isDesktopPlatform) { + if (Platform.isLinux && + UpdateManager.linuxEnvironment == LinuxPlatform.embedded) { + return false; + } + return true; + } + return false; +} + /// Configures the current window Future configureWindow() async { - await WindowManager.instance.ensureInitialized(); - await windowManager.waitUntilReadyToShow( - const WindowOptions( - minimumSize: kDebugMode ? Size(100, 100) : kInitialWindowSize, - // minimumSize: kInitialWindowSize, - skipTaskbar: false, - titleBarStyle: TitleBarStyle.hidden, - windowButtonVisibility: true, - ), - () async { - if ((isDesktopPlatform && Platform.isMacOS) || kDebugMode) { - await windowManager.setSize(kInitialWindowSize); - } - await windowManager.show(); - }, - ); + if (canConfigureWindow) { + await WindowManager.instance.ensureInitialized(); + await windowManager.waitUntilReadyToShow( + const WindowOptions( + minimumSize: kDebugMode ? Size(100, 100) : kInitialWindowSize, + // minimumSize: kInitialWindowSize, + skipTaskbar: false, + titleBarStyle: TitleBarStyle.hidden, + windowButtonVisibility: true, + ), + () async { + if ((isDesktopPlatform && Platform.isMacOS) || kDebugMode) { + await windowManager.setSize(kInitialWindowSize); + } + await windowManager.show(); + }, + ); + } } /// Configures the camera sub window @@ -58,8 +72,10 @@ Future configureWindow() async { /// /// * [SingleCameraWindow] Future configureWindowTitle(String title) async { - await WindowManager.instance.ensureInitialized(); - await windowManager.setTitle(title); + if (canConfigureWindow) { + await WindowManager.instance.ensureInitialized(); + await windowManager.setTitle(title); + } } enum MultiWindowType { device, layout } diff --git a/lib/widgets/desktop_buttons.dart b/lib/widgets/desktop_buttons.dart index daef6dc9..b26f1604 100644 --- a/lib/widgets/desktop_buttons.dart +++ b/lib/widgets/desktop_buttons.dart @@ -24,6 +24,7 @@ import 'package:bluecherry_client/main.dart'; import 'package:bluecherry_client/models/device.dart'; import 'package:bluecherry_client/models/event.dart'; import 'package:bluecherry_client/providers/home_provider.dart'; +import 'package:bluecherry_client/providers/update_provider.dart'; import 'package:bluecherry_client/utils/methods.dart'; import 'package:bluecherry_client/utils/widgets/squared_icon_button.dart'; import 'package:bluecherry_client/widgets/events/events_screen.dart'; @@ -229,7 +230,7 @@ class WindowButtons extends StatelessWidget { ), // Do not render the Window Buttons on web nor macOS. macOS // render the buttons natively. - if (!kIsWeb && !isMacOSPlatform) + if (!kIsWeb && !isMacOSPlatform && !UpdateManager.isEmbedded) SizedBox( width: 138, child: Builder(builder: (context) { diff --git a/lib/widgets/settings/mobile/settings.dart b/lib/widgets/settings/mobile/settings.dart index 5f57bf4d..82b8b360 100644 --- a/lib/widgets/settings/mobile/settings.dart +++ b/lib/widgets/settings/mobile/settings.dart @@ -62,7 +62,6 @@ class _MobileSettingsState extends State { final loc = AppLocalizations.of(context); final theme = Theme.of(context); final settings = context.watch(); - final update = context.watch(); final servers = context.watch(); return Material( @@ -161,7 +160,7 @@ class _MobileSettingsState extends State { ), ), const SliverToBoxAdapter(child: WakelockTile()), - if (update.isUpdatingSupported) ...[ + if (UpdateManager.isUpdatingSupported) ...[ SliverToBoxAdapter( child: SubHeader( loc.updates, diff --git a/lib/widgets/settings/shared/update.dart b/lib/widgets/settings/shared/update.dart index 06a958cb..ba94d254 100644 --- a/lib/widgets/settings/shared/update.dart +++ b/lib/widgets/settings/shared/update.dart @@ -360,12 +360,14 @@ class About extends StatelessWidget { padding: const EdgeInsetsDirectional.symmetric(horizontal: 24.0), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 8.0), - Text(update.packageInfo.version), - const SizedBox(height: 8.0), - Text( - loc.versionText, - style: theme.textTheme.displayMedium, - ), + if (update.packageInfo != null) ...[ + Text(update.packageInfo!.version), + const SizedBox(height: 8.0), + Text( + loc.versionText, + style: theme.textTheme.displayMedium, + ), + ], const SizedBox(height: 8.0), Link( uri: Uri.https('www.bluecherrydvr.com', '/'), diff --git a/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart b/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart index 09999a61..a6789629 100644 --- a/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart +++ b/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart @@ -6,18 +6,17 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutterpi_gstreamer_video_player/flutterpi_gstreamer_video_player.dart'; -import 'package:unity_video_player_main/unity_video_player_main.dart'; import 'package:video_player/video_player.dart'; import 'package:unity_video_player_platform_interface/unity_video_player_platform_interface.dart'; class UnityVideoPlayerFlutterInterface extends UnityVideoPlayerInterface { /// Registers this class as the default instance of [UnityVideoPlayerInterface]. static void registerWith() { - if ('pi' case const String.fromEnvironment('linux_environment')) { - UnityVideoPlayerInterface.instance = UnityVideoPlayerFlutterInterface(); - return; - } - UnityVideoPlayerInterface.instance = UnityVideoPlayerMediaKitInterface(); +// if ('pi' case const String.fromEnvironment('linux_environment')) { + UnityVideoPlayerInterface.instance = UnityVideoPlayerFlutterInterface(); +// return; +// } +// UnityVideoPlayerInterface.instance = UnityVideoPlayerMediaKitInterface(); } @override