This commit is contained in:
Alessandro Autiero
2024-06-01 16:26:00 +02:00
parent d478650e9b
commit efb508bd0c
243 changed files with 486662 additions and 2948 deletions

View File

@@ -1,119 +1,72 @@
import 'dart:collection';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:reboot_launcher/src/page/pages.dart';
import 'package:sync/semaphore.dart';
const infoBarLongDuration = Duration(seconds: 4);
const infoBarShortDuration = Duration(seconds: 2);
const _height = 64.0;
Semaphore _semaphore = Semaphore();
HashMap<int, _OverlayEntry> _overlays = HashMap();
void restoreMessage(int pageIndex, int lastIndex) {
removeMessageByPage(lastIndex);
final entry = _overlays[pageIndex];
if(entry == null) {
return;
InfoBarEntry showInfoBar(dynamic text, {
InfoBarSeverity severity = InfoBarSeverity.info,
bool loading = false,
Duration? duration = infoBarShortDuration,
void Function()? onDismissed,
Widget? action
}) {
final overlay = _buildOverlay(text, action, loading, severity);
final overlayEntry = InfoBarEntry(overlay: overlay, onDismissed: onDismissed);
if(duration != null) {
Future.delayed(duration)
.then((_) => WidgetsBinding.instance.addPostFrameCallback((timeStamp) => overlayEntry.close()));
}
Overlay.of(pageKey.currentContext!).insert(entry.overlay);
return overlayEntry;
}
OverlayEntry showInfoBar(dynamic text,
{InfoBarSeverity severity = InfoBarSeverity.info,
bool loading = false,
Duration? duration = infoBarShortDuration,
void Function()? onDismissed,
Widget? action}) {
try {
_semaphore.acquire();
removeMessageByPage(pageIndex.value);
final overlay = OverlayEntry(
builder: (context) => Padding(
padding: EdgeInsets.only(
bottom: hasPageButton ? 72.0 : 16.0
),
child: Align(
alignment: AlignmentDirectional.bottomCenter,
child: Container(
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 1000
),
child: Mica(
child: InfoBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if(text is Widget)
text,
if(text is String)
Text(text),
if(action != null)
action
],
),
isLong: false,
isIconVisible: true,
content: SizedBox(
width: double.infinity,
child: loading ? const Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 2.0),
child: ProgressBar(),
) : const SizedBox()
),
severity: severity
),
),
),
),
)
);
Overlay.of(pageKey.currentContext!).insert(overlay);
_overlays[pageIndex.value] = _OverlayEntry(
overlay: overlay,
onDismissed: onDismissed
);
if(duration != null) {
Future.delayed(duration).then((_) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
final currentOverlay = _overlays[pageIndex.value];
if(currentOverlay == overlay) {
if(overlay.mounted) {
overlay.remove();
}
Widget _buildOverlay(text, Widget? action, bool loading, InfoBarSeverity severity) => SizedBox(
width: double.infinity,
height: _height,
child: Mica(
child: InfoBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if(text is Widget)
text,
if(text is String)
Text(text),
if(action != null)
action
],
),
isLong: false,
isIconVisible: true,
content: SizedBox(
width: double.infinity,
child: loading ? const Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 2.0),
child: ProgressBar(),
) : const SizedBox()
),
severity: severity
),
),
);
_overlays.remove(pageIndex.value);
currentOverlay?.onDismissed?.call();
}
});
});
}
return overlay;
}finally {
_semaphore.release();
}
}
void removeMessageByPage(int index) {
final lastOverlay = _overlays[index];
if(lastOverlay != null) {
try {
lastOverlay.overlay.remove();
}catch(_) {
// Do not use .isMounted
// This is intended behaviour
}finally {
_overlays.remove(index);
lastOverlay.onDismissed?.call();
}
}
}
class _OverlayEntry {
final OverlayEntry overlay;
class InfoBarEntry {
final Widget overlay;
final void Function()? onDismissed;
_OverlayEntry({required this.overlay, required this.onDismissed});
InfoBarEntry({required this.overlay, required this.onDismissed}) {
final context = pageKey.currentContext;
if(context != null) {
infoBarAreaKey.currentState?.insertChild(overlay);
}
}
bool close() {
final result = infoBarAreaKey.currentState?.removeChild(overlay) ?? false;
if(result) {
onDismissed?.call();
}
return result;
}
}

View File

@@ -20,133 +20,116 @@ import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:sync/semaphore.dart';
extension ServerControllerDialog on ServerController {
Future<bool> toggleInteractive([bool showSuccessMessage = true]) async {
var stream = toggle();
var completer = Completer<bool>();
Future<bool> toggleInteractive() async {
final stream = toggle();
final completer = Completer<bool>();
InfoBarEntry? entry;
worker = stream.listen((event) {
print(event.type);
switch (event.type) {
case ServerResultType.starting:
showInfoBar(
translations.startingServer(controllerName),
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
break;
case ServerResultType.startSuccess:
if(showSuccessMessage) {
showInfoBar(
type.value == ServerType.local ? translations.checkedServer(controllerName) : translations.startedServer(controllerName),
severity: InfoBarSeverity.success
);
}
completer.complete(true);
break;
case ServerResultType.startError:
showInfoBar(
type.value == ServerType.local ? translations.localServerError(event.error ?? translations.unknownError, controllerName) : translations.startServerError(event.error ?? translations.unknownError, controllerName),
severity: InfoBarSeverity.error,
duration: infoBarLongDuration
);
break;
case ServerResultType.stopping:
showInfoBar(
translations.stoppingServer,
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
break;
case ServerResultType.stopSuccess:
if(showSuccessMessage) {
showInfoBar(
translations.stoppedServer(controllerName),
severity: InfoBarSeverity.success
);
}
completer.complete(true);
break;
case ServerResultType.stopError:
showInfoBar(
translations.stopServerError(
event.error ?? translations.unknownError, controllerName),
severity: InfoBarSeverity.error,
duration: infoBarLongDuration
);
break;
case ServerResultType.missingHostError:
showInfoBar(
translations.missingHostNameError(controllerName),
severity: InfoBarSeverity.error
);
break;
case ServerResultType.missingPortError:
showInfoBar(
translations.missingPortError(controllerName),
severity: InfoBarSeverity.error
);
break;
case ServerResultType.illegalPortError:
showInfoBar(
translations.illegalPortError(controllerName),
severity: InfoBarSeverity.error
);
break;
case ServerResultType.freeingPort:
showInfoBar(
translations.freeingPort(defaultPort),
loading: true,
duration: null
);
break;
case ServerResultType.freePortSuccess:
showInfoBar(
translations.freedPort(defaultPort),
severity: InfoBarSeverity.success,
duration: infoBarShortDuration
);
break;
case ServerResultType.freePortError:
showInfoBar(
translations.freePortError(event.error ?? translations.unknownError, controllerName),
severity: InfoBarSeverity.error,
duration: infoBarLongDuration
);
break;
case ServerResultType.pingingRemote:
if(started.value) {
showInfoBar(
translations.pingingRemoteServer(controllerName),
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
}
break;
case ServerResultType.pingingLocal:
showInfoBar(
translations.pingingLocalServer(controllerName, type().name),
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
break;
case ServerResultType.pingError:
showInfoBar(
translations.pingError(controllerName, type().name),
severity: InfoBarSeverity.error
);
break;
}
entry?.close();
entry = _handeEvent(event);
if(event.type.isError) {
completer.complete(false);
}else if(event.type.isSuccess) {
completer.complete(true);
}
});
return await completer.future;
}
InfoBarEntry _handeEvent(ServerResult event) {
switch (event.type) {
case ServerResultType.starting:
return showInfoBar(
translations.startingServer(controllerName),
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
case ServerResultType.startSuccess:
return showInfoBar(
type.value == ServerType.local ? translations.checkedServer(controllerName) : translations.startedServer(controllerName),
severity: InfoBarSeverity.success
);
case ServerResultType.startError:
return showInfoBar(
type.value == ServerType.local ? translations.localServerError(event.error ?? translations.unknownError, controllerName) : translations.startServerError(event.error ?? translations.unknownError, controllerName),
severity: InfoBarSeverity.error,
duration: infoBarLongDuration
);
case ServerResultType.stopping:
return showInfoBar(
translations.stoppingServer,
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
case ServerResultType.stopSuccess:
return showInfoBar(
translations.stoppedServer(controllerName),
severity: InfoBarSeverity.success
);
case ServerResultType.stopError:
return showInfoBar(
translations.stopServerError(
event.error ?? translations.unknownError, controllerName),
severity: InfoBarSeverity.error,
duration: infoBarLongDuration
);
case ServerResultType.missingHostError:
return showInfoBar(
translations.missingHostNameError(controllerName),
severity: InfoBarSeverity.error
);
case ServerResultType.missingPortError:
return showInfoBar(
translations.missingPortError(controllerName),
severity: InfoBarSeverity.error
);
case ServerResultType.illegalPortError:
return showInfoBar(
translations.illegalPortError(controllerName),
severity: InfoBarSeverity.error
);
case ServerResultType.freeingPort:
return showInfoBar(
translations.freeingPort(defaultPort),
loading: true,
duration: null
);
case ServerResultType.freePortSuccess:
return showInfoBar(
translations.freedPort(defaultPort),
severity: InfoBarSeverity.success,
duration: infoBarShortDuration
);
case ServerResultType.freePortError:
return showInfoBar(
translations.freePortError(event.error ?? translations.unknownError, controllerName),
severity: InfoBarSeverity.error,
duration: infoBarLongDuration
);
case ServerResultType.pingingRemote:
return showInfoBar(
translations.pingingRemoteServer(controllerName),
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
case ServerResultType.pingingLocal:
return showInfoBar(
translations.pingingLocalServer(controllerName, type().name),
severity: InfoBarSeverity.info,
loading: true,
duration: null
);
case ServerResultType.pingError:
return showInfoBar(
translations.pingError(controllerName, type().name),
severity: InfoBarSeverity.error
);
}
}
}
final Semaphore _publishingSemaphore = Semaphore();
@@ -158,7 +141,7 @@ extension MatchmakerControllerExtension on MatchmakerController {
}
Future<void> joinServer(String uuid, Map<String, dynamic> entry) async {
var id = entry["id"];
final id = entry["id"];
if(uuid == id) {
showInfoBar(
translations.joinSelfServer,
@@ -168,13 +151,13 @@ extension MatchmakerControllerExtension on MatchmakerController {
return;
}
var hashedPassword = entry["password"];
var hasPassword = hashedPassword != null;
var embedded = type.value == ServerType.embedded;
var author = entry["author"];
var encryptedIp = entry["ip"];
final hashedPassword = entry["password"];
final hasPassword = hashedPassword != null;
final embedded = type.value == ServerType.embedded;
final author = entry["author"];
final encryptedIp = entry["ip"];
if(!hasPassword) {
var valid = await _isServerValid(encryptedIp);
final valid = await _isServerValid(encryptedIp);
if(!valid) {
return;
}
@@ -183,7 +166,7 @@ extension MatchmakerControllerExtension on MatchmakerController {
return;
}
var confirmPassword = await _askForPassword();
final confirmPassword = await _askForPassword();
if(confirmPassword == null) {
return;
}
@@ -197,8 +180,8 @@ extension MatchmakerControllerExtension on MatchmakerController {
return;
}
var decryptedIp = aes256Decrypt(encryptedIp, confirmPassword);
var valid = await _isServerValid(decryptedIp);
final decryptedIp = aes256Decrypt(encryptedIp, confirmPassword);
final valid = await _isServerValid(decryptedIp);
if(!valid) {
return;
}
@@ -207,7 +190,7 @@ extension MatchmakerControllerExtension on MatchmakerController {
}
Future<bool> _isServerValid(String address) async {
var result = await pingGameServer(address);
final result = await pingGameServer(address);
if(result) {
return true;
}
@@ -304,9 +287,9 @@ extension HostingControllerExtension on HostingController {
ip = aes256Encrypt(ip, passwordText);
}
var supabase = Supabase.instance.client;
var hosts = supabase.from("hosting");
var payload = {
final supabase = Supabase.instance.client;
final hosts = supabase.from("hosting");
final payload = {
'name': name.text,
'description': description.text,
'author': author,