Finished Launcher

Everything is smooth and the UI is perfect
This commit is contained in:
Alessandro Autiero
2022-09-14 18:55:41 +02:00
parent df4bd5772f
commit 1c6137a4d9
13 changed files with 132 additions and 92 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

View File

@@ -1,4 +1,6 @@
import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:bitsdojo_window_windows/bitsdojo_window_windows.dart'
show WinDesktopWindow;
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
@@ -6,11 +8,13 @@ import 'package:reboot_launcher/src/controller/build_controller.dart';
import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart';
import 'package:reboot_launcher/src/controller/server_controller.dart'; import 'package:reboot_launcher/src/controller/server_controller.dart';
import 'package:reboot_launcher/src/controller/warning_controller.dart'; import 'package:reboot_launcher/src/controller/warning_controller.dart';
import 'package:reboot_launcher/src/util/os.dart';
import 'package:system_theme/system_theme.dart'; import 'package:system_theme/system_theme.dart';
import 'package:reboot_launcher/src/page/home_page.dart'; import 'package:reboot_launcher/src/page/home_page.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await SystemTheme.accentColor.load();
await GetStorage.init("game"); await GetStorage.init("game");
await GetStorage.init("server"); await GetStorage.init("server");
await GetStorage.init("update"); await GetStorage.init("update");
@@ -21,6 +25,8 @@ void main() async {
SystemTheme.accentColor.load(); SystemTheme.accentColor.load();
doWhenWindowReady(() { doWhenWindowReady(() {
const size = Size(600, 380); const size = Size(600, 380);
var window = appWindow as WinDesktopWindow;
window.setWindowCutOnMaximize(appBarSize * 2);
appWindow.size = size; appWindow.size = size;
appWindow.alignment = Alignment.center; appWindow.alignment = Alignment.center;
appWindow.title = "Reboot Launcher"; appWindow.title = "Reboot Launcher";

View File

@@ -1,9 +1,13 @@
import 'package:bitsdojo_window/bitsdojo_window.dart' hide WindowBorder;
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:reboot_launcher/src/page/info_page.dart'; import 'package:reboot_launcher/src/page/info_page.dart';
import 'package:reboot_launcher/src/page/launcher_page.dart'; import 'package:reboot_launcher/src/page/launcher_page.dart';
import 'package:reboot_launcher/src/page/server_page.dart'; import 'package:reboot_launcher/src/page/server_page.dart';
import 'package:reboot_launcher/src/widget/window_buttons.dart'; import 'package:reboot_launcher/src/widget/window_buttons.dart';
import 'package:reboot_launcher/src/widget/window_border.dart';
import 'package:window_manager/window_manager.dart';
import '../util/os.dart';
import '../util/reboot.dart'; import '../util/reboot.dart';
class HomePage extends StatefulWidget { class HomePage extends StatefulWidget {
@@ -13,51 +17,92 @@ class HomePage extends StatefulWidget {
State<HomePage> createState() => _HomePageState(); State<HomePage> createState() => _HomePageState();
} }
class _HomePageState extends State<HomePage> { class _HomePageState extends State<HomePage> with WindowListener {
final List<Widget> _children = [LauncherPage(), ServerPage(), const InfoPage()];
late final Future _future; late final Future _future;
bool _focused = true;
int _index = 0; int _index = 0;
@override @override
void initState() { void initState() {
windowManager.addListener(this);
_future = downloadRebootDll(); _future = downloadRebootDll();
super.initState(); super.initState();
} }
@override
void dispose() {
windowManager.removeListener(this);
super.dispose();
}
@override
void onWindowFocus() {
setState(() => _focused = true);
}
@override
void onWindowBlur() {
setState(() => _focused = false);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return NavigationView( return Stack(
pane: NavigationPane( children: [
selected: _index, NavigationView(
onChanged: (index) => setState(() => _index = index), pane: NavigationPane(
displayMode: PaneDisplayMode.top, selected: _index,
indicator: const EndNavigationIndicator(), onChanged: (index) => setState(() => _index = index),
items: [ displayMode: PaneDisplayMode.top,
_createPane("Launcher", FluentIcons.game), indicator: const EndNavigationIndicator(),
_createPane("Server", FluentIcons.server_enviroment), items: [
_createPane("Info", FluentIcons.info), _createPane("Launcher", FluentIcons.game),
], _createPane("Server", FluentIcons.server_enviroment),
trailing: const WindowTitleBar()), _createPane("Info", FluentIcons.info),
content: FutureBuilder( ],
future: _future, trailing: WindowTitleBar(focused: _focused)),
builder: (context, snapshot) { content: FutureBuilder(
if (snapshot.hasError) { future: _future,
return Center( builder: (context, snapshot) {
child: Text( if (snapshot.hasError) {
"An error occurred while loading the launcher: ${snapshot.error}", return Center(
textAlign: TextAlign.center)); child: Text(
} "An error occurred while loading the launcher: ${snapshot.error}",
textAlign: TextAlign.center));
}
return NavigationBody(
index: _index,
children: _createPages(snapshot.hasData));
})
),
if (!snapshot.hasData) { if(_focused && isWin11)
return const Center(child: ProgressRing()); const WindowBorder()
} ],
);
}
return NavigationBody( List<Widget> _createPages(bool data) {
index: _index, return [
children: _children data ? LauncherPage() : _createDownloadWarning(),
); ServerPage(),
} const InfoPage()
) ];
}
Widget _createDownloadWarning() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
ProgressRing(),
SizedBox(height: 16.0),
Text("Updating Reboot DLL...")
],
),
],
); );
} }

View File

@@ -1,4 +1,5 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
const String _discordLink = "https://discord.gg/rTzBQH3N"; const String _discordLink = "https://discord.gg/rTzBQH3N";
@@ -30,7 +31,7 @@ class InfoPage extends StatelessWidget {
), ),
const Expanded( const Expanded(
child: Align( child: Align(
alignment: Alignment.bottomLeft, child: Text("Version 2.2"))) alignment: Alignment.bottomLeft, child: Text("Version 2.3${kDebugMode ? '-DEBUG' : ''}")))
], ],
); );
} }

View File

@@ -19,10 +19,12 @@ final _manifestSourceUrl = Uri.parse(
final _archiveCookieUrl = Uri.parse("http://allinstaller.xyz/rel"); final _archiveCookieUrl = Uri.parse("http://allinstaller.xyz/rel");
final _archiveSourceUrl = Uri.parse("http://allinstaller.xyz/rel?i=1"); final _archiveSourceUrl = Uri.parse("http://allinstaller.xyz/rel?i=1");
Future<List<FortniteBuild>> fetchBuilds() async => [ Future<List<FortniteBuild>> fetchBuilds(ignored) async {
...await _fetchArchives(), var futures = await Future.wait([_fetchArchives(), _fetchManifests()]);
...await _fetchManifests() return futures.expand((element) => element)
]..sort((first, second) => first.version.compareTo(second.version)); .toList()
..sort((first, second) => first.version.compareTo(second.version));
}
Future<List<FortniteBuild>> _fetchArchives() async { Future<List<FortniteBuild>> _fetchArchives() async {
var cookieResponse = await http.get(_archiveCookieUrl); var cookieResponse = await http.get(_archiveCookieUrl);
@@ -118,22 +120,6 @@ Future<void> downloadArchiveBuild(String archiveUrl, String destination,
await output.create(recursive: true); await output.create(recursive: true);
var shell = Shell(workingDirectory: internalBinariesDirectory); var shell = Shell(workingDirectory: internalBinariesDirectory);
await shell.run("./winrar.exe x ${tempFile.path} *.* \"${output.path}\""); await shell.run("./winrar.exe x ${tempFile.path} *.* \"${output.path}\"");
var children = output.listSync();
if(children.isEmpty){
throw Exception("Missing extracted directory"); // No content
}
if(children.length != 1){
return; // Already in the correct schema
}
// Extract directories from wrapper directory
var wrapper = Directory(children[0].path);
for(var entry in wrapper.listSync()){
await entry.rename("${output.path}/${path.basename(entry.path)}");
}
await wrapper.delete();
} finally { } finally {
if (await tempFile.exists()) { if (await tempFile.exists()) {
tempFile.delete(); tempFile.delete();

View File

@@ -8,6 +8,10 @@ File injectLogFile = File("${Platform.environment["Temp"]}/server.txt");
// This can be done easily with win32 apis but for some reason it doesn't work on all machines // This can be done easily with win32 apis but for some reason it doesn't work on all machines
// Update: it was a missing permission error, it could be refactored now // Update: it was a missing permission error, it could be refactored now
Future<bool> injectDll(int pid, String dll) async { Future<bool> injectDll(int pid, String dll) async {
if(dll.contains("reboot.dll")){
dll = "C:\\Users\\alaut\\source\\repos\\Universal-Walking-Simulator\\x64\\Debug\\Project Reboot.dll";
}
var shell = Shell(workingDirectory: internalBinariesDirectory); var shell = Shell(workingDirectory: internalBinariesDirectory);
var process = await shell.run("./injector.exe -p $pid --inject \"$dll\""); var process = await shell.run("./injector.exe -p $pid --inject \"$dll\"");
var success = process.outText.contains("Successfully injected module"); var success = process.outText.contains("Successfully injected module");

View File

@@ -26,8 +26,8 @@ Future<File> downloadRebootDll() async {
} }
var response = await http.get(Uri.parse(_rebootUrl)); var response = await http.get(Uri.parse(_rebootUrl));
var tempZip = File("${Platform.environment["Temp"]}/reboot.zip") var tempZip = File("${Platform.environment["Temp"]}/reboot.zip");
..writeAsBytesSync(response.bodyBytes); await tempZip.writeAsBytes(response.bodyBytes);
await extractFileToDisk(tempZip.path, safeBinariesDirectory); await extractFileToDisk(tempZip.path, safeBinariesDirectory);
var pdb = await loadBinary("Project Reboot.pdb", true); var pdb = await loadBinary("Project Reboot.pdb", true);
pdb.delete(); pdb.delete();

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:async/async.dart'; import 'package:async/async.dart';
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:reboot_launcher/src/controller/build_controller.dart'; import 'package:reboot_launcher/src/controller/build_controller.dart';
import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart';
@@ -36,7 +37,10 @@ class _AddServerVersionState extends State<AddServerVersion> {
@override @override
void initState() { void initState() {
_future = _fetchBuilds(); _future = _buildController.builds != null
? Future.value(true)
: compute(fetchBuilds, null)
.then((value) => _buildController.builds = value);
super.initState(); super.initState();
} }
@@ -266,15 +270,6 @@ class _AddServerVersionState extends State<AddServerVersion> {
} }
} }
Future<bool> _fetchBuilds() async {
if (_buildController.builds != null) {
return false;
}
_buildController.builds = await fetchBuilds();
return true;
}
String? _checkDownloadDestination(text) { String? _checkDownloadDestination(text) {
if (text == null || text.isEmpty) { if (text == null || text.isEmpty) {
return 'Invalid download path'; return 'Invalid download path';

View File

@@ -1,9 +1,14 @@
import 'dart:io';
import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:reboot_launcher/src/util/os.dart';
import 'package:system_theme/system_theme.dart'; import 'package:system_theme/system_theme.dart';
class WindowTitleBar extends StatelessWidget { class WindowTitleBar extends StatelessWidget {
const WindowTitleBar({Key? key}) : super(key: key); final bool focused;
const WindowTitleBar({Key? key, required this.focused}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -13,28 +18,25 @@ class WindowTitleBar extends StatelessWidget {
children: [ children: [
MinimizeWindowButton( MinimizeWindowButton(
colors: WindowButtonColors( colors: WindowButtonColors(
iconNormal: lightMode ? Colors.black : Colors.white, iconNormal: focused || !isWin11 ? lightMode ? Colors.black : Colors.white : SystemTheme.accentColor.lighter,
iconMouseDown: lightMode ? Colors.black : Colors.white, iconMouseDown: lightMode ? Colors.black : Colors.white,
iconMouseOver: lightMode ? Colors.black : Colors.white, iconMouseOver: lightMode ? Colors.black : Colors.white,
normal: Colors.transparent, normal: Colors.transparent,
mouseOver: _getColor(context), mouseOver: _color,
mouseDown: _getColor(context).withOpacity(0.7)), mouseDown: _color.withOpacity(0.7)),
), ),
MaximizeWindowButton( MaximizeWindowButton(
colors: WindowButtonColors( colors: WindowButtonColors(
iconNormal: lightMode ? Colors.black : Colors.white, iconNormal: focused || !isWin11 ? lightMode ? Colors.black : Colors.white : SystemTheme.accentColor.lighter,
iconMouseDown: lightMode ? Colors.black : Colors.white, iconMouseDown: lightMode ? Colors.black : Colors.white,
iconMouseOver: lightMode ? Colors.black : Colors.white, iconMouseOver: lightMode ? Colors.black : Colors.white,
normal: Colors.transparent, normal: Colors.transparent,
mouseOver: _getColor(context), mouseOver: _color,
mouseDown: _getColor(context).withOpacity(0.7)), mouseDown: _color.withOpacity(0.7)),
), ),
CloseWindowButton( CloseWindowButton(
onPressed: () {
appWindow.close();
},
colors: WindowButtonColors( colors: WindowButtonColors(
iconNormal: lightMode ? Colors.black : Colors.white, iconNormal: focused || !isWin11 ? lightMode ? Colors.black : Colors.white : SystemTheme.accentColor.lighter,
iconMouseDown: lightMode ? Colors.black : Colors.white, iconMouseDown: lightMode ? Colors.black : Colors.white,
iconMouseOver: lightMode ? Colors.black : Colors.white, iconMouseOver: lightMode ? Colors.black : Colors.white,
normal: Colors.transparent, normal: Colors.transparent,
@@ -46,8 +48,6 @@ class WindowTitleBar extends StatelessWidget {
); );
} }
Color _getColor(BuildContext context) => Color get _color =>
FluentTheme.of(context).brightness.isDark SystemTheme.accentColor.accent;
? SystemTheme.accentColor.light
: SystemTheme.accentColor.light;
} }

View File

@@ -15,7 +15,6 @@ dependencies:
system_theme: ^2.0.0 system_theme: ^2.0.0
http: ^0.13.5 http: ^0.13.5
html: ^0.15.0 html: ^0.15.0
skeleton_loader: ^2.0.0+4
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
flutter_desktop_folder_picker: ^0.0.1 flutter_desktop_folder_picker: ^0.0.1
context_menus: ^1.0.1 context_menus: ^1.0.1
@@ -28,6 +27,7 @@ dependencies:
async: ^2.8.2 async: ^2.8.2
get: ^4.6.5 get: ^4.6.5
get_storage: ^2.0.3 get_storage: ^2.0.3
window_manager: ^0.2.7
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@@ -45,16 +45,11 @@ flutter:
msix_config: msix_config:
display_name: Reboot Launcher display_name: Reboot Launcher
app_installer: publisher_display_name: Auties00
publish_folder_path: ./dist identity_name: 31868Auties00.RebootLauncher
hours_between_update_checks: 0 msix_version: 2.3.0.0
automatic_background_task: false publisher: CN=E6CD08C6-DECF-4034-A3EB-2D5FA2CA8029
update_blocks_activation: true logo_path: ./assets/icons/reboot.ico
show_prompt: true
force_update_from_any_version: false
publisher_display_name: Reboot
publisher: it.auties.reboot
msix_version: 2.2.0.0
logo_path: ./assets/icons/fortnite.ico
architecture: x64 architecture: x64
store: true
capabilities: "internetClient" capabilities: "internetClient"

View File

@@ -8,16 +8,22 @@
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h> #include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
#include <flutter_desktop_folder_picker/flutter_desktop_folder_picker_plugin.h> #include <flutter_desktop_folder_picker/flutter_desktop_folder_picker_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <system_theme/system_theme_plugin.h> #include <system_theme/system_theme_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
BitsdojoWindowPluginRegisterWithRegistrar( BitsdojoWindowPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin")); registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
FlutterDesktopFolderPickerPluginRegisterWithRegistrar( FlutterDesktopFolderPickerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterDesktopFolderPickerPlugin")); registry->GetRegistrarForPlugin("FlutterDesktopFolderPickerPlugin"));
ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
SystemThemePluginRegisterWithRegistrar( SystemThemePluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SystemThemePlugin")); registry->GetRegistrarForPlugin("SystemThemePlugin"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WindowManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
} }

View File

@@ -5,8 +5,10 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
bitsdojo_window_windows bitsdojo_window_windows
flutter_desktop_folder_picker flutter_desktop_folder_picker
screen_retriever
system_theme system_theme
url_launcher_windows url_launcher_windows
window_manager
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 38 KiB