From bfe15e43d98ce052769fef7d76691a6294e6b43c Mon Sep 17 00:00:00 2001 From: Alessandro Autiero Date: Sat, 14 Sep 2024 12:37:56 +0200 Subject: [PATCH] Released 9.2.7 --- common/lib/src/util/build.dart | 4 +- common/pubspec.yaml | 2 +- gui/lib/l10n/reboot_en.arb | 4 +- gui/lib/src/controller/dll_controller.dart | 21 +- .../src/messenger/implementation/error.dart | 9 +- .../src/messenger/implementation/version.dart | 18 +- .../src/page/implementation/backend_page.dart | 4 +- .../src/page/implementation/home_page.dart | 78 +++-- .../src/page/implementation/host_page.dart | 266 +++++++++--------- .../page/implementation/settings_page.dart | 4 +- gui/lib/src/util/types.dart | 11 + gui/lib/src/widget/file_selector.dart | 2 +- gui/lib/src/widget/file_setting_tile.dart | 128 ++++++--- gui/lib/src/widget/info_bar_area.dart | 33 ++- gui/pubspec.yaml | 2 +- 15 files changed, 331 insertions(+), 255 deletions(-) diff --git a/common/lib/src/util/build.dart b/common/lib/src/util/build.dart index 390c137..85db2a9 100644 --- a/common/lib/src/util/build.dart +++ b/common/lib/src/util/build.dart @@ -133,9 +133,9 @@ Future _downloadArchive(FortniteBuildDownloadOptions options, Completer st throw _genericError; }, headers: byteStart == null || byteStart <= 0 ? { - "Cookie": "_c_t_c=1" + } : { - "Cookie": "_c_t_c=1", + "Range": "bytes=${byteStart}-" }, ) diff --git a/common/pubspec.yaml b/common/pubspec.yaml index 1fff3ba..06d0be2 100644 --- a/common/pubspec.yaml +++ b/common/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ">=3.0.0 <=4.0.0" dependencies: - dio: ^5.3.2 + dio: ^5.7.0 win32: 3.0.0 ffi: ^2.1.0 path: ^1.8.3 diff --git a/gui/lib/l10n/reboot_en.arb b/gui/lib/l10n/reboot_en.arb index 9560ed0..bd91976 100644 --- a/gui/lib/l10n/reboot_en.arb +++ b/gui/lib/l10n/reboot_en.arb @@ -368,5 +368,7 @@ "automaticGameServerDialogStart": "Start server", "gameResetDefaultsName": "Reset", "gameResetDefaultsDescription": "Resets the game's settings to their default values", - "gameResetDefaultsContent": "Reset" + "gameResetDefaultsContent": "Reset", + "selectFile": "Select a file", + "reset": "Reset" } diff --git a/gui/lib/src/controller/dll_controller.dart b/gui/lib/src/controller/dll_controller.dart index fd67697..b953248 100644 --- a/gui/lib/src/controller/dll_controller.dart +++ b/gui/lib/src/controller/dll_controller.dart @@ -109,7 +109,9 @@ class DllController extends GetxController { duration: null ); } - timestamp.value = await downloadRebootDll(url.text); + final result = downloadRebootDll(url.text); + timestamp.value = await Future.wait([result, Future.delayed(const Duration(seconds: 1))], eagerError: false) + .then((_) => result); status.value = UpdateStatus.success; infoBarEntry?.close(); if(!silent) { @@ -126,15 +128,18 @@ class DllController extends GetxController { error = error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error; error = error.toLowerCase(); status.value = UpdateStatus.error; - showRebootInfoBar( - translations.downloadDllError("reboot.dll", error.toString()), + infoBarEntry = showRebootInfoBar( + translations.downloadDllError(error.toString(), "reboot.dll"), duration: infoBarLongDuration, severity: InfoBarSeverity.error, action: Button( - onPressed: () => updateGameServerDll( - force: true, - silent: silent - ), + onPressed: () async { + infoBarEntry?.close(); + updateGameServerDll( + force: true, + silent: silent + ); + }, child: Text(translations.downloadDllRetry), ) ); @@ -215,7 +220,7 @@ class DllController extends GetxController { error = error.toLowerCase(); final completer = Completer(); await showRebootInfoBar( - translations.downloadDllError(fileName, error.toString()), + translations.downloadDllError(error.toString(), fileName), duration: infoBarLongDuration, severity: InfoBarSeverity.error, onDismissed: () => completer.complete(null), diff --git a/gui/lib/src/messenger/implementation/error.dart b/gui/lib/src/messenger/implementation/error.dart index 802aa6b..7d9bad9 100644 --- a/gui/lib/src/messenger/implementation/error.dart +++ b/gui/lib/src/messenger/implementation/error.dart @@ -18,9 +18,12 @@ void onError(Object exception, StackTrace? stackTrace, bool framework) { } lastError = exception.toString(); - final route = ModalRoute.of(pageKey.currentContext!); - if(route != null && !route.isCurrent){ - Navigator.of(pageKey.currentContext!).pop(false); + if(inDialog){ + final context = pageKey.currentContext; + if(context != null) { + Navigator.of(context).pop(false); + inDialog = false; + } } WidgetsBinding.instance.addPostFrameCallback((timeStamp) => showRebootDialog( diff --git a/gui/lib/src/messenger/implementation/version.dart b/gui/lib/src/messenger/implementation/version.dart index 27297cd..068788b 100644 --- a/gui/lib/src/messenger/implementation/version.dart +++ b/gui/lib/src/messenger/implementation/version.dart @@ -5,10 +5,13 @@ import 'dart:isolate'; import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; import 'package:reboot_common/common.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/messenger/abstract/dialog.dart'; +import 'package:reboot_launcher/src/util/os.dart'; import 'package:reboot_launcher/src/util/translations.dart'; +import 'package:reboot_launcher/src/util/types.dart'; import 'package:reboot_launcher/src/widget/file_selector.dart'; import 'package:universal_disk_space/universal_disk_space.dart'; import 'package:windows_taskbar/windows_taskbar.dart'; @@ -41,6 +44,7 @@ class _AddVersionDialogState extends State { SendPort? _downloadPort; Object? _error; StackTrace? _stackTrace; + bool _selecting = false; @override void initState() { @@ -102,7 +106,12 @@ class _AddVersionDialogState extends State { return ErrorDialog( exception: _error ?? Exception(translations.unknownError), stackTrace: _stackTrace, - errorMessageBuilder: (exception) => translations.downloadVersionError(exception.toString()) + errorMessageBuilder: (exception) { + var error = exception.toString(); + error = error.after("Error: ")?.replaceAll(":", ",") ?? error.after(": ") ?? error; + error = error.toLowerCase(); + return translations.downloadVersionError(error); + } ); case _DownloadStatus.done: return InfoDialog( @@ -274,7 +283,8 @@ class _AddVersionDialogState extends State { ); } - Widget _buildFormBody(List builds) => Column( + Widget _buildFormBody(List builds) { + return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -292,7 +302,8 @@ class _AddVersionDialogState extends State { windowTitle: _source.value == _BuildSource.local ? translations.gameFolderPlaceWindowTitle : translations.buildInstallationDirectoryWindowTitle, controller: _pathController, validator: _source.value == _BuildSource.local ? _checkGameFolder : _checkDownloadDestination, - folder: true + folder: true, + allowNavigator: true ), const SizedBox( @@ -300,6 +311,7 @@ class _AddVersionDialogState extends State { ) ], ); + } String? _checkGameFolder(text) { if (text == null || text.isEmpty) { diff --git a/gui/lib/src/page/implementation/backend_page.dart b/gui/lib/src/page/implementation/backend_page.dart index a043b3f..bde6d25 100644 --- a/gui/lib/src/page/implementation/backend_page.dart +++ b/gui/lib/src/page/implementation/backend_page.dart @@ -153,9 +153,9 @@ class _BackendPageState extends RebootPageState { contentWidth: null, content: Row( children: [ - Text( + Obx(() => Text( _backendController.detached.value ? translations.on : translations.off - ), + )), const SizedBox( width: 16.0 ), diff --git a/gui/lib/src/page/implementation/home_page.dart b/gui/lib/src/page/implementation/home_page.dart index 31808d2..8d292b5 100644 --- a/gui/lib/src/page/implementation/home_page.dart +++ b/gui/lib/src/page/implementation/home_page.dart @@ -298,48 +298,46 @@ class _HomePageState extends State with WindowListener, AutomaticKeepA }); } - Widget _buildBody() { - return Expanded( - child: Padding( - padding: EdgeInsets.only( - left: HomePage.kDefaultPadding, - right: HomePage.kDefaultPadding * 2, - top: HomePage.kDefaultPadding, - bottom: HomePage.kDefaultPadding * 2 - ), - child: Column( - children: [ - Expanded( - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: 1000 - ), - child: Center( - child: Column( - children: [ - _buildBodyHeader(), - const SizedBox(height: 24.0), - Expanded( - child: Stack( - fit: StackFit.loose, - children: [ - _buildBodyContent(), - InfoBarArea( - key: infoBarAreaKey - ) - ], - ) - ), - ], - ), + Widget _buildBody() => Expanded( + child: Padding( + padding: EdgeInsets.only( + left: HomePage.kDefaultPadding, + right: HomePage.kDefaultPadding * 2, + top: HomePage.kDefaultPadding, + bottom: HomePage.kDefaultPadding * 2 + ), + child: Column( + children: [ + Expanded( + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: 1000 + ), + child: Center( + child: Column( + children: [ + _buildBodyHeader(), + const SizedBox(height: 24.0), + Expanded( + child: Stack( + fit: StackFit.loose, + children: [ + _buildBodyContent(), + InfoBarArea( + key: infoBarAreaKey + ) + ], + ) + ), + ], ), ), - ) - ], - ) - ), - ); - } + ), + ) + ], + ) + ), + ); Widget _buildBodyContent() => PageView.builder( controller: _pageController, diff --git a/gui/lib/src/page/implementation/host_page.dart b/gui/lib/src/page/implementation/host_page.dart index 351b14f..1d74321 100644 --- a/gui/lib/src/page/implementation/host_page.dart +++ b/gui/lib/src/page/implementation/host_page.dart @@ -82,7 +82,7 @@ class _HostingPageState extends RebootPageState { List get settings => [ _information, buildVersionSelector( - key: hostVersionOverlayTargetKey + key: hostVersionOverlayTargetKey ), _options, _internalFiles, @@ -175,9 +175,9 @@ class _HostingPageState extends RebootPageState { contentWidth: null, content: Obx(() => Row( children: [ - Text( + Obx(() => Text( _hostingController.discoverable.value ? translations.on : translations.off - ), + )), const SizedBox( width: 16.0 ), @@ -226,7 +226,7 @@ class _HostingPageState extends RebootPageState { text: Text(entry.translatedName), onPressed: () => _hostingController.type.value = entry )).toList(), - disabled: _settingsController.debug.value + disabled: _settingsController.debug.value )), ), SettingTile( @@ -238,9 +238,9 @@ class _HostingPageState extends RebootPageState { contentWidth: null, content: Row( children: [ - Text( + Obx(() => Text( _hostingController.autoRestart.value ? translations.on : translations.off - ), + )), const SizedBox( width: 16.0 ), @@ -278,151 +278,143 @@ class _HostingPageState extends RebootPageState { title: Text(translations.settingsServerName), subtitle: Text(translations.settingsServerSubtitle), children: [ - SettingTile( - icon: Icon( - FluentIcons.timer_24_regular - ), - title: Text(translations.settingsServerTypeName), - subtitle: Text(translations.settingsServerTypeDescription), - content: Obx(() => DropDownButton( - onOpen: () => inDialog = true, - onClose: () => inDialog = false, - leading: Text(_dllController.customGameServer.value ? translations.settingsServerTypeCustomName : translations.settingsServerTypeEmbeddedName), - items: { - false: translations.settingsServerTypeEmbeddedName, - true: translations.settingsServerTypeCustomName - }.entries.map((entry) => MenuFlyoutItem( - text: Text(entry.value), - onPressed: () { - final oldValue = _dllController.customGameServer.value; - if(oldValue == entry.key) { - return; - } + _internalFilesServerType, + _internalFilesUpdateTimer, + _internalFilesServerSource + ], + ); - _dllController.customGameServer.value = entry.key; - _dllController.infoBarEntry?.close(); - if(!entry.key) { - _dllController.updateGameServerDll( - force: true - ); - } - } - )).toList() - )) + Widget get _internalFilesServerType => SettingTile( + icon: Icon( + FluentIcons.games_24_regular ), - Obx(() { - if(!_dllController.customGameServer.value) { - return const SizedBox.shrink(); - } + title: Text(translations.settingsServerTypeName), + subtitle: Text(translations.settingsServerTypeDescription), + contentWidth: SettingTile.kDefaultContentWidth + 30, + content: Obx(() => DropDownButton( + onOpen: () => inDialog = true, + onClose: () => inDialog = false, + leading: Text(_dllController.customGameServer.value ? translations.settingsServerTypeCustomName : translations.settingsServerTypeEmbeddedName), + items: { + false: translations.settingsServerTypeEmbeddedName, + true: translations.settingsServerTypeCustomName + }.entries.map((entry) => MenuFlyoutItem( + text: Text(entry.value), + onPressed: () { + final oldValue = _dllController.customGameServer.value; + if(oldValue == entry.key) { + return; + } - return createFileSetting( - title: translations.settingsServerFileName, - description: translations.settingsServerFileDescription, - controller: _dllController.gameServerDll, - onReset: () { - final path = _dllController.getDefaultDllPath(InjectableDll.reboot); - _dllController.gameServerDll.text = path; - _dllController.downloadCriticalDllInteractive(path); - } - ); - }), - Obx(() { - if(_dllController.customGameServer.value) { - return const SizedBox.shrink(); - } + _dllController.customGameServer.value = entry.key; + _dllController.infoBarEntry?.close(); + if(!entry.key) { + _dllController.updateGameServerDll( + force: true + ); + } + } + )).toList() + )) + ); - return SettingTile( - icon: Icon( - FluentIcons.globe_24_regular - ), - title: Text(translations.settingsServerMirrorName), - subtitle: Text(translations.settingsServerMirrorDescription), - content: Row( - children: [ - Expanded( - child: TextFormBox( - placeholder: translations.settingsServerMirrorPlaceholder, - controller: _dllController.url, - validator: _checkUpdateUrl - ), - ), - const SizedBox(width: 8.0), - Button( - style: ButtonStyle( - padding: ButtonState.all(EdgeInsets.zero) - ), - onPressed: () => _dllController.url.text = kRebootDownloadUrl, - child: SizedBox.square( - dimension: 30, - child: Icon( - FluentIcons.arrow_reset_24_regular - ), - ) - ) - ], - ) - ); - }), - Obx(() { - if(_dllController.customGameServer.value) { - return const SizedBox.shrink(); - } - - return SettingTile( - icon: Icon( - FluentIcons.timer_24_regular - ), - title: Text(translations.settingsServerTimerName), - subtitle: Text(translations.settingsServerTimerSubtitle), - content: Row( - children: [ - Expanded( - child: Obx(() => DropDownButton( - onOpen: () => inDialog = true, - onClose: () => inDialog = false, - leading: Text(_dllController.timer.value.text), - items: UpdateTimer.values.map((entry) => MenuFlyoutItem( - text: Text(entry.text), - onPressed: () { - _dllController.timer.value = entry; - _dllController.infoBarEntry?.close(); - _dllController.updateGameServerDll( - force: true - ); - } - )).toList() - )), - ), - const SizedBox(width: 8.0), - Button( - style: ButtonStyle( - padding: ButtonState.all(EdgeInsets.zero) - ), - onPressed: () { - _dllController.updateGameServerDll(force: true); + Widget get _internalFilesServerSource => Obx(() { + if(!_dllController.customGameServer.value) { + return SettingTile( + icon: Icon( + FluentIcons.globe_24_regular + ), + title: Text(translations.settingsServerMirrorName), + subtitle: Text(translations.settingsServerMirrorDescription), + contentWidth: SettingTile.kDefaultContentWidth + 30, + content: Row( + children: [ + Expanded( + child: TextFormBox( + placeholder: translations.settingsServerMirrorPlaceholder, + controller: _dllController.url, + onChanged: (value) { + if(Uri.tryParse(value) != null) { + _dllController.updateGameServerDll(force: true); + } }, + ), + ), + const SizedBox(width: 8.0), + Button( + style: ButtonStyle( + padding: ButtonState.all(EdgeInsets.zero) + ), + onPressed: () => _dllController.updateGameServerDll(force: true), child: SizedBox.square( dimension: 30, child: Icon( FluentIcons.arrow_download_24_regular ), ) - ) - ], - ) - ); - }) - ], - ); + ), + const SizedBox(width: 8.0), + Button( + style: ButtonStyle( + padding: ButtonState.all(EdgeInsets.zero) + ), + onPressed: () { + _dllController.url.text = kRebootDownloadUrl; + _dllController.updateGameServerDll(force: true); + }, + child: SizedBox.square( + dimension: 30, + child: Icon( + FluentIcons.arrow_reset_24_regular + ), + ) + ) + ], + ) + ); + }else { + return createFileSetting( + title: translations.settingsServerFileName, + description: translations.settingsServerFileDescription, + controller: _dllController.gameServerDll, + onReset: () { + final path = _dllController.getDefaultDllPath(InjectableDll.reboot); + _dllController.gameServerDll.text = path; + _dllController.downloadCriticalDllInteractive(path); + } + ); + } + }); - - String? _checkUpdateUrl(String? text) { - if (text == null || text.isEmpty) { - return translations.emptyURL; + Widget get _internalFilesUpdateTimer => Obx(() { + if(_dllController.customGameServer.value) { + return const SizedBox.shrink(); } - return null; - } + return SettingTile( + icon: Icon( + FluentIcons.timer_24_regular + ), + title: Text(translations.settingsServerTimerName), + subtitle: Text(translations.settingsServerTimerSubtitle), + contentWidth: SettingTile.kDefaultContentWidth + 30, + content: Obx(() => DropDownButton( + onOpen: () => inDialog = true, + onClose: () => inDialog = false, + leading: Text(_dllController.timer.value.text), + items: UpdateTimer.values.map((entry) => MenuFlyoutItem( + text: Text(entry.text), + onPressed: () { + _dllController.timer.value = entry; + _dllController.infoBarEntry?.close(); + _dllController.updateGameServerDll( + force: true + ); + } + )).toList() + )) + ); + }); SettingTile get _share => SettingTile( icon: Icon( diff --git a/gui/lib/src/page/implementation/settings_page.dart b/gui/lib/src/page/implementation/settings_page.dart index 9d50a42..ab5983e 100644 --- a/gui/lib/src/page/implementation/settings_page.dart +++ b/gui/lib/src/page/implementation/settings_page.dart @@ -110,9 +110,9 @@ class _SettingsPageState extends RebootPageState { contentWidth: null, content: Row( children: [ - Text( + Obx(() => Text( _settingsController.debug.value ? translations.on : translations.off - ), + )), const SizedBox( width: 16.0 ), diff --git a/gui/lib/src/util/types.dart b/gui/lib/src/util/types.dart index dd8c68a..706d461 100644 --- a/gui/lib/src/util/types.dart +++ b/gui/lib/src/util/types.dart @@ -5,4 +5,15 @@ extension IterableExtension on Iterable { } return null; } +} + +extension StringExtension on String { + String? after(String leading) { + final index = indexOf(leading); + if(index == -1) { + return null; + } + + return substring(index + leading.length); + } } \ No newline at end of file diff --git a/gui/lib/src/widget/file_selector.dart b/gui/lib/src/widget/file_selector.dart index 4111ae2..4c08b32 100644 --- a/gui/lib/src/widget/file_selector.dart +++ b/gui/lib/src/widget/file_selector.dart @@ -19,10 +19,10 @@ class FileSelector extends StatefulWidget { required this.controller, required this.validator, required this.folder, + required this.allowNavigator, this.label, this.extension, this.validatorMode, - this.allowNavigator = true, Key? key}) : assert(folder || extension != null, "Missing extension for file selector"), super(key: key); diff --git a/gui/lib/src/widget/file_setting_tile.dart b/gui/lib/src/widget/file_setting_tile.dart index 8d33e6b..796216a 100644 --- a/gui/lib/src/widget/file_setting_tile.dart +++ b/gui/lib/src/widget/file_setting_tile.dart @@ -1,70 +1,120 @@ import 'dart:io'; import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons; +import 'package:fluent_ui/fluent_ui.dart' as fluentIcons show FluentIcons; import 'package:fluentui_system_icons/fluentui_system_icons.dart'; +import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; +import 'package:reboot_launcher/src/util/os.dart'; import 'package:reboot_launcher/src/util/translations.dart'; import 'package:reboot_launcher/src/widget/file_selector.dart'; import 'package:reboot_launcher/src/widget/setting_tile.dart'; +const double _kButtonDimensions = 30; +const double _kButtonSpacing = 8; + SettingTile createFileSetting({required String title, required String description, required TextEditingController controller, required void Function() onReset}) { final obx = RxString(controller.text); controller.addListener(() => obx.value = controller.text); - return SettingTile( - icon: Icon( - FluentIcons.document_24_regular - ), - title: Text(title), - subtitle: Text(description), - content: Row( + final selecting = RxBool(false); + return SettingTile( + icon: Icon( + FluentIcons.document_24_regular + ), + title: Text(title), + subtitle: Text(description), + contentWidth: SettingTile.kDefaultContentWidth + _kButtonDimensions * 2 + _kButtonSpacing * 2, + content: Row( children: [ - Expanded( - child: FileSelector( - placeholder: translations.selectPathPlaceholder, - windowTitle: translations.selectPathWindowTitle, - controller: controller, - validator: _checkDll, - extension: "dll", - folder: false, - validatorMode: AutovalidateMode.always - ), + Expanded( + child: FileSelector( + placeholder: translations.selectPathPlaceholder, + windowTitle: translations.selectPathWindowTitle, + controller: controller, + validator: _checkDll, + extension: "dll", + folder: false, + validatorMode: AutovalidateMode.always, + allowNavigator: false, ), - const SizedBox(width: 8.0), - Obx(() => Padding( - padding: EdgeInsets.only( - bottom: _checkDll(obx.value) == null ? 0.0 : 20.0 + ), + const SizedBox(width: _kButtonSpacing), + Obx(() => Padding( + padding: EdgeInsets.only( + bottom: _checkDll(obx.value) == null ? 0.0 : 20.0 + ), + child: Tooltip( + message: translations.selectFile, + child: Button( + style: ButtonStyle( + padding: ButtonState.all(EdgeInsets.zero) + ), + onPressed: () => _onPressed(selecting, controller), + child: SizedBox.square( + dimension: _kButtonDimensions, + child: Icon( + fluentIcons.FluentIcons.open_folder_horizontal + ), + ) ), + ), + )), + const SizedBox(width: _kButtonSpacing), + Obx(() => Padding( + padding: EdgeInsets.only( + bottom: _checkDll(obx.value) == null ? 0.0 : 20.0 + ), + child: Tooltip( + message: translations.reset, child: Button( style: ButtonStyle( padding: ButtonState.all(EdgeInsets.zero) ), onPressed: onReset, child: SizedBox.square( - dimension: 30, - child: Icon( - FluentIcons.arrow_reset_24_regular - ), + dimension: _kButtonDimensions, + child: Icon( + FluentIcons.arrow_reset_24_regular + ), ) ), - )) + ), + )) ], - ) -); + ) + ); +} + +void _onPressed(RxBool selecting, TextEditingController controller) { + if(selecting.value){ + return; + } + + selecting.value = true; + compute(openFilePicker, "dll") + .then((value) => _updateText(controller, value)) + .then((_) => selecting.value = false); +} + +void _updateText(TextEditingController controller, String? value) { + final text = value ?? controller.text; + controller.text = text; + controller.selection = TextSelection.collapsed(offset: text.length); } String? _checkDll(String? text) { - if (text == null || text.isEmpty) { - return translations.invalidDllPath; - } + if (text == null || text.isEmpty) { + return translations.invalidDllPath; + } - final file = File(text); - if (!file.existsSync()) { - return translations.dllDoesNotExist; - } + final file = File(text); + if (!file.existsSync()) { + return translations.dllDoesNotExist; + } - if (!text.endsWith(".dll")) { - return translations.invalidDllExtension; - } + if (!text.endsWith(".dll")) { + return translations.invalidDllExtension; + } - return null; + return null; } \ No newline at end of file diff --git a/gui/lib/src/widget/info_bar_area.dart b/gui/lib/src/widget/info_bar_area.dart index f730c12..9443bbc 100644 --- a/gui/lib/src/widget/info_bar_area.dart +++ b/gui/lib/src/widget/info_bar_area.dart @@ -24,19 +24,22 @@ class InfoBarAreaState extends State { } @override - Widget build(BuildContext context) => Obx(() => Padding( - padding: EdgeInsets.only( - bottom: hasPageButton ? 72.0 : 16.0 - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.start, - children: _children.value.map((child) => Padding( - padding: EdgeInsets.only( - top: 12.0 - ), - child: child - )).toList(growable: false) - ), - )); + Widget build(BuildContext context) => StreamBuilder( + stream: pagesController.stream, + builder: (context, _) => Obx(() => Padding( + padding: EdgeInsets.only( + bottom: hasPageButton ? 72.0 : 16.0 + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: _children.value.map((child) => Padding( + padding: EdgeInsets.only( + top: 12.0 + ), + child: child + )).toList(growable: false) + ), + )) + ); } \ No newline at end of file diff --git a/gui/pubspec.yaml b/gui/pubspec.yaml index 5f5bafb..93b094f 100644 --- a/gui/pubspec.yaml +++ b/gui/pubspec.yaml @@ -1,6 +1,6 @@ name: reboot_launcher description: Graphical User Interface for Project Reboot -version: "9.2.6" +version: "9.2.7" publish_to: 'none'