Refactored GUI

This commit is contained in:
Alessandro Autiero
2025-08-10 19:43:57 +01:00
parent 52abf5eb95
commit 4ea73d17c7
75 changed files with 2020 additions and 2011 deletions

View File

@@ -1,16 +1,13 @@
import 'dart:convert';
import 'package:dart_ipify/dart_ipify.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:reboot_common/common.dart';
import 'package:reboot_launcher/main.dart';
import 'package:reboot_launcher/src/util/cryptography.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:sync/semaphore.dart';
import 'package:uuid/uuid.dart';
import '../util/cryptography.dart';
class HostingController extends GetxController {
static const String storageName = "v3_hosting_storage";
@@ -25,15 +22,12 @@ class HostingController extends GetxController {
late final TextEditingController password;
late final FocusNode passwordFocusNode;
late final RxBool showPassword;
late final RxBool discoverable;
late final RxBool headless;
late final RxBool autoRestart;
late final RxBool started;
late final RxBool published;
late final Rxn<GameInstance> instance;
late final Rxn<Set<FortniteServer>> servers;
late final TextEditingController customLaunchArgs;
late final Semaphore _semaphore;
HostingController() {
_storage = appWithNoStorage ? null : GetStorage(storageName);
@@ -52,8 +46,6 @@ class HostingController extends GetxController {
nameFocusNode = FocusNode();
descriptionFocusNode = FocusNode();
passwordFocusNode = FocusNode();
discoverable = RxBool(_storage?.read("discoverable") ?? false);
discoverable.listen((value) => _storage?.write("discoverable", value));
headless = RxBool(_storage?.read("headless") ?? true);
headless.listen((value) => _storage?.write("headless", value));
autoRestart = RxBool(_storage?.read("auto_restart") ?? true);
@@ -62,119 +54,38 @@ class HostingController extends GetxController {
published = RxBool(false);
showPassword = RxBool(false);
instance = Rxn();
servers = Rxn();
_listenServers();
customLaunchArgs = TextEditingController(text: _storage?.read("custom_launch_args") ?? "");
customLaunchArgs.addListener(() => _storage?.write("custom_launch_args", customLaunchArgs.text));
_semaphore = Semaphore();
}
void _listenServers([int attempt = 0]) {
log("[SUPABASE] Listening...");
final supabase = Supabase.instance.client;
supabase.from("hosting_v2")
.stream(primaryKey: ['id'])
.map((event) => event.map((element) => FortniteServer.fromJson(element)).where((element) => element.ip.isNotEmpty).toSet())
.listen(
_onNewServer,
onError: (error) async {
log("[SUPABASE] Error: ${error}");
await Future.delayed(Duration(seconds: attempt * 5));
_listenServers(attempt + 1);
},
cancelOnError: true
Future<ServerBrowserEntry> createServerBrowserEntry() async {
final passwordText = password.text;
final hasPassword = passwordText.isNotEmpty;
var ip = await Ipify.ipv4();
if(hasPassword) {
ip = aes256Encrypt(ip, passwordText);
}
return ServerBrowserEntry(
id: uuid,
name: name.text,
description: description.text,
author: accountUsername.text,
ip: ip,
version: instance.value!.version.toString(),
password: hasPassword ? hashPassword(passwordText) : "",
timestamp: DateTime.now()
);
}
void _onNewServer(Set<FortniteServer> event) {
log("[SUPABASE] New event: ${event}");
servers.value = event;
published.value = event.any((element) => element.id == uuid);
}
Future<void> publishServer(String author, String version) async {
try {
_semaphore.acquire();
log("[SERVER] Publishing server...");
if(published.value) {
log("[SERVER] Already published");
return;
}
final passwordText = password.text;
final hasPassword = passwordText.isNotEmpty;
var ip = await Ipify.ipv4();
if(hasPassword) {
ip = aes256Encrypt(ip, passwordText);
}
final supabase = Supabase.instance.client;
final hosts = supabase.from("hosting_v2");
final payload = FortniteServer(
id: uuid,
name: name.text,
description: description.text,
author: author,
ip: ip,
version: version,
password: hasPassword ? hashPassword(passwordText) : null,
timestamp: DateTime.now(),
discoverable: discoverable.value
).toJson();
log("[SERVER] Payload: ${jsonEncode(payload)}");
if(published()) {
await hosts.update(payload)
.eq("id", uuid);
}else {
await hosts.insert(payload);
}
published.value = true;
log("[SERVER] Published");
}catch(error) {
log("[SERVER] Cannot publish server: $error");
published.value = false;
}finally {
_semaphore.release();
}
}
Future<void> discardServer() async {
try {
_semaphore.acquire();
log("[SERVER] Discarding server...");
final supabase = Supabase.instance.client;
await supabase.from("hosting_v2")
.delete()
.match({'id': uuid});
servers.value?.removeWhere((element) => element.id == uuid);
log("[SERVER] Discarded server");
}catch(error) {
log("[SERVER] Cannot discard server: $error");
}finally {
published.value = false;
_semaphore.release();
}
}
void reset() {
accountUsername.text = kDefaultHostName;
accountPassword.text = "";
name.text = "";
description.text = "";
showPassword.value = false;
discoverable.value = false;
instance.value = null;
headless.value = true;
autoRestart.value = true;
customLaunchArgs.text = "";
}
FortniteServer? findServerById(String uuid) {
try {
return servers.value?.firstWhere((element) => element.id == uuid);
} on StateError catch(_) {
return null;
}
}
}