using System.Diagnostics; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using FluentAvalonia.UI.Controls; using LanMountainDesktop.Launcher.Resources; using LanMountainDesktop.Launcher.Services; namespace LanMountainDesktop.Launcher.Views; public partial class ErrorWindow : Window { private const int DebugModeClickThreshold = 5; private readonly TaskCompletionSource _completionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); private int _iconClickCount; private bool _isDebugMode; private bool _devModeEnabled; private string? _customHostPath; private ErrorWindowResult _primaryAction = ErrorWindowResult.Retry; private ErrorWindowResult? _secondaryAction; public ErrorWindow() { AvaloniaXamlLoader.Load(this); _devModeEnabled = LoadDevModeStateInternal(); _customHostPath = LoadCustomHostPathInternal(); Loaded += OnWindowLoaded; Closed += (_, _) => _completionSource.TrySetResult(ErrorWindowResult.Exit); ConfigureForGenericFailure(allowRetry: true); } public void SetErrorMessage(string message) { var normalizedMessage = string.IsNullOrWhiteSpace(message) ? Strings.Error_MessageNotReached : message.Trim(); var firstLine = normalizedMessage .Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries) .FirstOrDefault() ?? normalizedMessage; if (this.FindControl("ErrorMessageText") is { } errorText) { errorText.Text = firstLine; } if (this.FindControl("ErrorDetailsTextBox") is { } detailsTextBox) { detailsTextBox.Text = normalizedMessage; } } public void SetDebugMode(bool isDebugMode) { _isDebugMode = isDebugMode; if (isDebugMode && this.FindControl("TitleText") is { } titleText) { titleText.Text = Strings.Error_DebugTitle; } } public void ConfigureForHostNotFound() { ApplyActionLayout( title: Strings.Error_HostNotFoundTitle, suggestion: Strings.Error_HostNotFoundMessage, primaryLabel: Strings.Error_ButtonRetry, primaryAction: ErrorWindowResult.Retry, secondaryLabel: null, secondaryAction: null); } public void ConfigureForGenericFailure(bool allowRetry) { ApplyActionLayout( title: Strings.Error_TitleCannotConfirm, suggestion: allowRetry ? Strings.Error_GenericRetryMessage : Strings.Error_GenericNoRetryMessage, primaryLabel: allowRetry ? Strings.Error_ButtonRetry : Strings.Error_ButtonActivate, primaryAction: allowRetry ? ErrorWindowResult.Retry : ErrorWindowResult.ActivateExisting, secondaryLabel: allowRetry ? null : Strings.Error_ButtonWait, secondaryAction: allowRetry ? null : ErrorWindowResult.ContinueWaiting); } public void ConfigureForRunningHostFailure(int? hostPid) { var suggestion = hostPid is > 0 ? string.Format(Strings.Error_PendingMessageWithPid, hostPid) : Strings.Error_PendingMessage; ApplyActionLayout( title: Strings.Error_PendingTitle, suggestion: suggestion, primaryLabel: Strings.Error_ButtonActivate, primaryAction: ErrorWindowResult.ActivateExisting, secondaryLabel: Strings.Error_ButtonWait, secondaryAction: ErrorWindowResult.ContinueWaiting); } public string? GetCustomHostPath() => _customHostPath; public bool IsDevModeEnabled() => _devModeEnabled; public Task WaitForChoiceAsync() => _completionSource.Task; public static bool CheckDevModeEnabled() => LoadDevModeStateInternal(); public static string? GetSavedCustomHostPath() => LoadCustomHostPathInternal(); private void OnWindowLoaded(object? sender, RoutedEventArgs e) { if (this.FindControl("ErrorIconBorder") is { } errorIconBorder) { errorIconBorder.PointerPressed += OnErrorIconClick; } if (this.FindControl