Skip to content

Commit

Permalink
feat: Embedded platforms support
Browse files Browse the repository at this point in the history
  • Loading branch information
bdlukaa authored Jan 7, 2024
2 parents 6c5a0d5 + 79e2d05 commit 794123b
Show file tree
Hide file tree
Showing 16 changed files with 224 additions and 138 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: "stable"
cache: false

- 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
12 changes: 11 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<NavigatorState>();
Expand All @@ -80,6 +82,14 @@ Future<void> main(List<String> 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');
Expand Down Expand Up @@ -189,7 +199,7 @@ class _UnityAppState extends State<UnityApp>
super.initState();
WidgetsBinding.instance.addObserver(this);
windowManager.addListener(this);
if (isDesktopPlatform) {
if (isDesktopPlatform && canConfigureWindow) {
windowManager.setPreventClose(true).then((_) {
if (mounted) setState(() {});
});
Expand Down
2 changes: 1 addition & 1 deletion lib/models/layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions lib/providers/home_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<SettingsProvider>();

if (!settings.wakelockEnabled) {
Expand Down
12 changes: 9 additions & 3 deletions lib/providers/settings_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down
82 changes: 59 additions & 23 deletions lib/providers/update_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,44 @@ 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'),
embedded(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.embedded || _ => 'Embedded'
};
}
}

class UpdateManager extends UnityProvider {
UpdateManager._();

/// `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<UpdateManager> ensureInitialized() async {
instance = UpdateManager._();
await instance.initialize();
Expand All @@ -104,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(
Expand All @@ -130,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) {
Expand Down Expand Up @@ -196,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`
Expand All @@ -205,15 +228,28 @@ 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.embedded;
}

return LinuxPlatform.values.firstWhere(
(linux) =>
linux.value == const String.fromEnvironment('linux_environment'),
orElse: () => LinuxPlatform.embedded,
);
}

return const String.fromEnvironment('linux_environment');
/// 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.
Expand All @@ -222,11 +258,11 @@ class UpdateManager extends UnityProvider {
///
/// 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 != null &&
linuxEnvironment != UpdateVersion.appImage;
return linuxEnvironment != LinuxPlatform.appImage &&
linuxEnvironment != LinuxPlatform.embedded;
}

return false;
Expand Down Expand Up @@ -285,7 +321,6 @@ class UpdateManager extends UnityProvider {
fileName = UpdateVersion.windowsDownloadFileName;
extension = '.exe';
} else if (Platform.isLinux) {
assert(linuxEnvironment != null);
fileName = UpdateVersion.linuxDownloadFileName;
extension = '.$linuxEnvironment';
} else {
Expand Down Expand Up @@ -351,16 +386,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.embedded:
case LinuxPlatform.appImage:
throw UnsupportedError('AppImages do not support updating from app');
default:
throw UnsupportedError(
Expand Down
5 changes: 4 additions & 1 deletion lib/utils/methods.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -138,7 +139,9 @@ bool get isCupertino {
/// is connected to a WiFi network, then it returns 400, otherwise it returns
/// 200.
Future<int> get eventsLimit async {
final connectivityResult = await Connectivity().checkConnectivity();
final connectivityResult = UpdateManager.isEmbedded
? ConnectivityResult.wifi
: await Connectivity().checkConnectivity();

switch (connectivityResult) {
case ConnectivityResult.wifi:
Expand Down
Loading

0 comments on commit 794123b

Please sign in to comment.