mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 03:02:22 +01:00
Released 9.2.7
This commit is contained in:
@@ -133,9 +133,9 @@ Future<void> _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}-"
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<AddVersionDialog> {
|
||||
SendPort? _downloadPort;
|
||||
Object? _error;
|
||||
StackTrace? _stackTrace;
|
||||
bool _selecting = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -102,7 +106,12 @@ class _AddVersionDialogState extends State<AddVersionDialog> {
|
||||
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<AddVersionDialog> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFormBody(List<FortniteBuild> builds) => Column(
|
||||
Widget _buildFormBody(List<FortniteBuild> builds) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -292,7 +302,8 @@ class _AddVersionDialogState extends State<AddVersionDialog> {
|
||||
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<AddVersionDialog> {
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
String? _checkGameFolder(text) {
|
||||
if (text == null || text.isEmpty) {
|
||||
|
||||
@@ -153,9 +153,9 @@ class _BackendPageState extends RebootPageState<BackendPage> {
|
||||
contentWidth: null,
|
||||
content: Row(
|
||||
children: [
|
||||
Text(
|
||||
Obx(() => Text(
|
||||
_backendController.detached.value ? translations.on : translations.off
|
||||
),
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 16.0
|
||||
),
|
||||
|
||||
@@ -298,48 +298,46 @@ class _HomePageState extends State<HomePage> 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,
|
||||
|
||||
@@ -82,7 +82,7 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
List<Widget> get settings => [
|
||||
_information,
|
||||
buildVersionSelector(
|
||||
key: hostVersionOverlayTargetKey
|
||||
key: hostVersionOverlayTargetKey
|
||||
),
|
||||
_options,
|
||||
_internalFiles,
|
||||
@@ -175,9 +175,9 @@ class _HostingPageState extends RebootPageState<HostPage> {
|
||||
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<HostPage> {
|
||||
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<HostPage> {
|
||||
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<HostPage> {
|
||||
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(
|
||||
|
||||
@@ -110,9 +110,9 @@ class _SettingsPageState extends RebootPageState<SettingsPage> {
|
||||
contentWidth: null,
|
||||
content: Row(
|
||||
children: [
|
||||
Text(
|
||||
Obx(() => Text(
|
||||
_settingsController.debug.value ? translations.on : translations.off
|
||||
),
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 16.0
|
||||
),
|
||||
|
||||
@@ -6,3 +6,14 @@ extension IterableExtension<E> on Iterable<E> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
extension StringExtension on String {
|
||||
String? after(String leading) {
|
||||
final index = indexOf(leading);
|
||||
if(index == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return substring(index + leading.length);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -24,19 +24,22 @@ class InfoBarAreaState extends State<InfoBarArea> {
|
||||
}
|
||||
|
||||
@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)
|
||||
),
|
||||
))
|
||||
);
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user