mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 03:02:22 +01:00
Refactored GUI
This commit is contained in:
@@ -13,12 +13,12 @@ import 'package:reboot_launcher/src/controller/backend_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/dll_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/game_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/hosting_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/server_browser_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/settings_controller.dart';
|
||||
import 'package:reboot_launcher/src/widget/message/error.dart';
|
||||
import 'package:reboot_launcher/src/widget/page/home_page.dart';
|
||||
import 'package:reboot_launcher/src/message/error.dart';
|
||||
import 'package:reboot_launcher/src/pager/pager.dart';
|
||||
import 'package:reboot_launcher/src/util/os.dart';
|
||||
import 'package:reboot_launcher/src/util/url_protocol.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:system_theme/system_theme.dart';
|
||||
import 'package:version/version.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
@@ -35,207 +35,140 @@ bool appWithNoStorage = false;
|
||||
void main() {
|
||||
log("[APP] Called");
|
||||
runZonedGuarded(
|
||||
() => _startApp(),
|
||||
(error, stack) => onError(error, stack, false),
|
||||
() => _startApp(),
|
||||
(error, stack) => onError(error, stack, false),
|
||||
zoneSpecification: ZoneSpecification(
|
||||
handleUncaughtError: (self, parent, zone, error, stacktrace) => onError(error, stacktrace, false)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// If anything fails here, the app won't start
|
||||
// Be extremely careful
|
||||
Future<void> _startApp() async {
|
||||
_overrideHttpCertificate();
|
||||
final errors = <Object>[];
|
||||
final errors = <String>[];
|
||||
Future<T?> runCatching<T>({
|
||||
required FutureOr<T> Function() callable,
|
||||
required String Function(Object) errorFormatter
|
||||
}) async {
|
||||
try {
|
||||
return callable();
|
||||
}catch(error) {
|
||||
errors.add(errorFormatter(error));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
log("[APP] Starting application");
|
||||
try {
|
||||
log("[APP] Starting application");
|
||||
final pathError = await _initPath();
|
||||
if(pathError != null) {
|
||||
errors.add(pathError);
|
||||
}
|
||||
|
||||
final databaseError = await _initDatabase();
|
||||
if(databaseError != null) {
|
||||
errors.add(databaseError);
|
||||
}
|
||||
|
||||
final notificationsError = await _initNotifications();
|
||||
if(notificationsError != null) {
|
||||
errors.add(notificationsError);
|
||||
}
|
||||
|
||||
final versionError = await _initVersion();
|
||||
if(versionError != null) {
|
||||
errors.add(versionError);
|
||||
}
|
||||
|
||||
final storageErrors = await _initStorage();
|
||||
errors.addAll(storageErrors);
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
_initWindow();
|
||||
|
||||
final urlError = await _initUrlHandler();
|
||||
if(urlError != null) {
|
||||
errors.add(urlError);
|
||||
}
|
||||
}catch(uncaughtError) {
|
||||
errors.add(uncaughtError);
|
||||
} finally{
|
||||
await runCatching(
|
||||
callable: () => installationDirectory.create(
|
||||
recursive: true
|
||||
),
|
||||
errorFormatter: (error) => "Cannot create installation directory: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () => localNotifier.setup(
|
||||
appName: 'Reboot Launcher',
|
||||
shortcutPolicy: ShortcutPolicy.ignore
|
||||
),
|
||||
errorFormatter: (error) => "Cannot create installation directory: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () async {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
appVersion = Version.parse(packageInfo.version);
|
||||
},
|
||||
errorFormatter: (error) => "Cannot parse version: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () async {
|
||||
await GetStorage(GameController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(BackendController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(SettingsController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(HostingController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(DllController.storageName, settingsDirectory.path).initStorage;
|
||||
},
|
||||
errorFormatter: (error) {
|
||||
appWithNoStorage = true;
|
||||
return "Cannot access storage: $error";
|
||||
}
|
||||
);
|
||||
await runCatching(
|
||||
callable: () => Get.put(GameController(), permanent: true),
|
||||
errorFormatter: (error) => "Cannot create game controller: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () => Get.put(BackendController(), permanent: true),
|
||||
errorFormatter: (error) => "Cannot create backend controller: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () => Get.put(HostingController(), permanent: true),
|
||||
errorFormatter: (error) => "Cannot create backend controller: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () => Get.put(ServerBrowserController(), permanent: true),
|
||||
errorFormatter: (error) => "Cannot create browser controller: $error"
|
||||
);
|
||||
final settingsController = await runCatching(
|
||||
callable: () => Get.put(SettingsController(), permanent: true),
|
||||
errorFormatter: (error) => "Cannot create settings controller: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () => Get.put(DllController(), permanent: true),
|
||||
errorFormatter: (error) => "Cannot create dll controller: $error"
|
||||
);
|
||||
await runCatching(
|
||||
callable: () async {
|
||||
try {
|
||||
await SystemTheme.accentColor.load();
|
||||
await windowManager.ensureInitialized();
|
||||
await Window.initialize();
|
||||
if(settingsController != null) {
|
||||
final size = Size(settingsController.width, settingsController.height);
|
||||
await windowManager.setSize(size);
|
||||
final offsetX = settingsController.offsetX;
|
||||
final offsetY = settingsController.offsetY;
|
||||
if (offsetX != null && offsetY != null) {
|
||||
final position = Offset(
|
||||
offsetX,
|
||||
offsetY
|
||||
);
|
||||
await windowManager.setPosition(position);
|
||||
} else {
|
||||
await windowManager.setAlignment(Alignment.center);
|
||||
}
|
||||
}
|
||||
await windowManager.setPreventClose(true);
|
||||
await windowManager.setResizable(true);
|
||||
if(isWin11) {
|
||||
await Window.setEffect(
|
||||
effect: WindowEffect.acrylic,
|
||||
color: Colors.green,
|
||||
dark: isDarkMode
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
windowManager.show();
|
||||
}
|
||||
},
|
||||
errorFormatter: (error) => "Cannot configure window: $error"
|
||||
);
|
||||
runCatching(
|
||||
callable: () => registerUrlProtocol(kCustomUrlSchema, arguments: ['%s']),
|
||||
errorFormatter: (error) => "Cannot configure custom url scheme: $error"
|
||||
);
|
||||
}catch(error) {
|
||||
errors.add("Uncaught error: $error");
|
||||
}finally {
|
||||
log("[APP] Started applications with errors: $errors");
|
||||
runApp(RebootApplication(errors: errors));
|
||||
}
|
||||
}
|
||||
|
||||
class _MyHttpOverrides extends HttpOverrides {
|
||||
@override
|
||||
HttpClient createHttpClient(SecurityContext? context){
|
||||
return super.createHttpClient(context)
|
||||
..badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
|
||||
}
|
||||
}
|
||||
|
||||
void _overrideHttpCertificate() {
|
||||
HttpOverrides.global = _MyHttpOverrides(); // Not safe, but necessary
|
||||
}
|
||||
|
||||
Future<Object?> _initNotifications() async {
|
||||
try {
|
||||
await localNotifier.setup(
|
||||
appName: 'Reboot Launcher',
|
||||
shortcutPolicy: ShortcutPolicy.ignore
|
||||
);
|
||||
return null;
|
||||
}catch(error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Object?> _initDatabase() async {
|
||||
try {
|
||||
await Supabase.initialize(
|
||||
url: supabaseUrl,
|
||||
anonKey: supabaseAnonKey
|
||||
);
|
||||
return null;
|
||||
}catch(error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Object?> _initPath() async {
|
||||
try {
|
||||
await installationDirectory.create(recursive: true);
|
||||
return null;
|
||||
}catch(error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Object?> _initVersion() async {
|
||||
try {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
appVersion = Version.parse(packageInfo.version);
|
||||
return null;
|
||||
}catch(error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Object?> _initUrlHandler() async {
|
||||
try {
|
||||
registerUrlProtocol(kCustomUrlSchema, arguments: ['%s']);
|
||||
return null;
|
||||
}catch(error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initWindow() async {
|
||||
try {
|
||||
await SystemTheme.accentColor.load();
|
||||
await windowManager.ensureInitialized();
|
||||
await Window.initialize();
|
||||
var settingsController = Get.find<SettingsController>();
|
||||
var size = Size(settingsController.width, settingsController.height);
|
||||
await windowManager.setSize(size);
|
||||
var offsetX = settingsController.offsetX;
|
||||
var offsetY = settingsController.offsetY;
|
||||
if(offsetX != null && offsetY != null) {
|
||||
final position = Offset(
|
||||
offsetX,
|
||||
offsetY
|
||||
);
|
||||
await windowManager.setPosition(position);
|
||||
}else {
|
||||
await windowManager.setAlignment(Alignment.center);
|
||||
}
|
||||
await windowManager.setPreventClose(true);
|
||||
await windowManager.setResizable(true);
|
||||
if(isWin11) {
|
||||
await Window.setEffect(
|
||||
effect: WindowEffect.acrylic,
|
||||
color: Colors.green,
|
||||
dark: isDarkMode
|
||||
);
|
||||
}
|
||||
}catch(error, stackTrace) {
|
||||
onError(error, stackTrace, false);
|
||||
}finally {
|
||||
windowManager.show();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Object>> _initStorage() async {
|
||||
final errors = <Object>[];
|
||||
try {
|
||||
await GetStorage(GameController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(BackendController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(SettingsController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(HostingController.storageName, settingsDirectory.path).initStorage;
|
||||
await GetStorage(DllController.storageName, settingsDirectory.path).initStorage;
|
||||
}catch(error) {
|
||||
appWithNoStorage = true;
|
||||
errors.add("The Reboot Launcher configuration in ${settingsDirectory.path} cannot be accessed: running with in memory storage");
|
||||
}
|
||||
|
||||
try {
|
||||
Get.put(GameController());
|
||||
}catch(error) {
|
||||
errors.add(error);
|
||||
}
|
||||
|
||||
try {
|
||||
Get.put(BackendController());
|
||||
}catch(error) {
|
||||
errors.add(error);
|
||||
}
|
||||
|
||||
try {
|
||||
final controller = HostingController();
|
||||
Get.put(controller);
|
||||
controller.discardServer();
|
||||
}catch(error) {
|
||||
errors.add(error);
|
||||
}
|
||||
|
||||
try {
|
||||
Get.put(SettingsController());
|
||||
}catch(error) {
|
||||
errors.add(error);
|
||||
}
|
||||
|
||||
try {
|
||||
Get.put(DllController());
|
||||
}catch(error) {
|
||||
errors.add(error);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
class RebootApplication extends StatefulWidget {
|
||||
final List<Object> errors;
|
||||
final List<String> errors;
|
||||
const RebootApplication({Key? key, required this.errors}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -248,15 +181,12 @@ class _RebootApplicationState extends State<RebootApplication> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) => _handleErrors(widget.errors));
|
||||
}
|
||||
|
||||
void _handleErrors(List<Object?> errors) {
|
||||
for(final error in errors) {
|
||||
if(error != null) {
|
||||
// Not pretty but make sure the errors are shown
|
||||
Future.delayed(const Duration(seconds: 5)).then((_) {
|
||||
for(final error in widget.errors) {
|
||||
onError(error, null, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -272,7 +202,7 @@ class _RebootApplicationState extends State<RebootApplication> {
|
||||
color: SystemTheme.accentColor.accent.toAccentColor(),
|
||||
darkTheme: _createTheme(Brightness.dark),
|
||||
theme: _createTheme(Brightness.light),
|
||||
home: const HomePage()
|
||||
home: const RebootPager()
|
||||
));
|
||||
|
||||
FluentThemeData _createTheme(Brightness brightness) => FluentThemeData(
|
||||
|
||||
Reference in New Issue
Block a user