using System.Reflection;
using System.Text.Json;
using CommunityToolkit.Mvvm.Input;
using XFEEDToolBox.Controls;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Views;
namespace XFEEDToolBox;
public partial class App
{
private static async Task RunRelogProbeAsync(string path)
{
var directory = Path.GetDirectoryName(Path.GetFullPath(path))!;
Directory.CreateDirectory(directory);
string? failure = null;
object? result = null;
static void Require(bool value, string message) { if (!value) throw new InvalidOperationException(message); }
try
{
Require(ViewModel.OfflinePreview && Runtime.FlightDriver is null && Runtime.Journal.Sequence == 0,
"The relog fixture requires an isolated offline runtime without a game connection.");
MainWindow.AppWindow.Move(new(-30000, -30000));
MainWindow.AppWindow.Resize(new(1680, 1080));
MainWindow.AppWindow.Show(false);
var projector = (PlayerProjector)typeof(JournalMonitor).GetField("projector", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(Runtime.Journal)!;
using var load = JsonDocument.Parse("""{"timestamp":"2026-10-23T00:00:00Z","event":"LoadGame","FID":"OFFLINE-RELOG","Commander":"离线按钮验证","GameMode":"Solo","Ship":"sidewinder"}""");
projector.Apply(load.RootElement);
ViewModel.DemoMode = false;
await ViewModel.RefreshCommand.ExecuteAsync(null);
AppShellPage.Current!.Navigate(typeof(MainPage));
await Task.Delay(350);
var page = (MainPage)AppShellPage.Current.CurrentPage!;
var button = Descendants(page).OfType<Button>().Single(b => b.Content is DependencyObject content
&& Descendants(content).OfType<TextBlock>().Any(t => t.Text == "一键重进"));
ViewModel.PluginRelogReady = false;
await Task.Delay(50);
Require(!button.IsEnabled && ViewModel.RelogAvailabilityText.Contains("更新"), "Old plugins must show their real disabled reason.");
ViewModel.PluginRelogReady = true;
await Task.Delay(80);
Require(button.IsEnabled && ViewModel.RelogGameCommand.CanExecute(null), "The actual dashboard button did not enable with the session capability.");
Require(Descendants(button).OfType<TextBlock>().Any(t => t.Text == "返回主菜单并重新进入单人模式"), "The actual mode hint is missing.");
Require(!Descendants(button).OfType<TextBlock>().Any(t => t.Text.Contains("接口验证中")), "The placeholder status survived.");
await CaptureRefinementElementAsync(button, Path.Combine(directory, "ready.png"));
var idle = button.Content;
var originalCommand = AsyncAction.GetCommand(button);
var originalCancel = AsyncAction.GetCancelCommand(button);
var countBefore = Descendants(page).OfType<Button>().Count();
var cancelled = 0;
// Only this synthetic action is run. The production relog command is
// queried above for availability and is never invoked by the probe.
var fake = new AsyncRelayCommand(async token =>
{
try { await Task.Delay(Timeout.Infinite, token); }
catch (OperationCanceledException) { cancelled++; }
});
AsyncAction.SetCommand(button, fake);
AsyncAction.SetCancelCommand(button, new RelayCommand(fake.Cancel));
var operation = fake.ExecuteAsync(null);
await Task.Delay(60);
Require(button.IsEnabled && button.Content as string == "取消", "The same initiating button must remain cancellable.");
Require(Descendants(page).OfType<Button>().Count() == countBefore, "A separate cancel button appeared.");
await CaptureRefinementElementAsync(button, Path.Combine(directory, "cancel.png"));
button.Command.Execute(null);
await operation.WaitAsync(TimeSpan.FromSeconds(2));
await Task.Delay(50);
Require(cancelled == 1 && ReferenceEquals(idle, button.Content), "Cancellation did not restore the original button.");
AsyncAction.SetCommand(button, originalCommand);
AsyncAction.SetCancelCommand(button, originalCancel);
result = new { oldPluginDisabled = true, readyButtonEnabled = true, originalModeHint = true, sameButtonCancellation = true,
cancelled, gameMenuCalls = 0, gameFlightCalls = 0, gameProcessChanges = 0 };
}
catch (Exception error) { failure = error.ToString(); }
await File.WriteAllTextAsync(path, JsonSerializer.Serialize(new { result, failure, offline = true }, new JsonSerializerOptions { WriteIndented = true }));
MainWindow.Close();
}
}
using System.Reflection;
using System.Text.Json;
using CommunityToolkit.Mvvm.Input;
using XFEEDToolBox.Controls;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Views;
namespace XFEEDToolBox;
public partial class App
{
private static async Task RunRelogProbeAsync(string path)
{
var directory = Path.GetDirectoryName(Path.GetFullPath(path))!;
Directory.CreateDirectory(directory);
string? failure = null;
object? result = null;
static void Require(bool value, string message) { if (!value) throw new InvalidOperationException(message); }
try
{
Require(ViewModel.OfflinePreview && Runtime.FlightDriver is null && Runtime.Journal.Sequence == 0,
"The relog fixture requires an isolated offline runtime without a game connection.");
MainWindow.AppWindow.Move(new(-30000, -30000));
MainWindow.AppWindow.Resize(new(1680, 1080));
MainWindow.AppWindow.Show(false);
var projector = (PlayerProjector)typeof(JournalMonitor).GetField("projector", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(Runtime.Journal)!;
using var load = JsonDocument.Parse("""{"timestamp":"2026-10-23T00:00:00Z","event":"LoadGame","FID":"OFFLINE-RELOG","Commander":"离线按钮验证","GameMode":"Solo","Ship":"sidewinder"}""");
projector.Apply(load.RootElement);
ViewModel.DemoMode = false;
await ViewModel.RefreshCommand.ExecuteAsync(null);
AppShellPage.Current!.Navigate(typeof(MainPage));
await Task.Delay(350);
var page = (MainPage)AppShellPage.Current.CurrentPage!;
var button = Descendants(page).OfType<Button>().Single(b => b.Content is DependencyObject content
&& Descendants(content).OfType<TextBlock>().Any(t => t.Text == "一键重进"));
ViewModel.PluginRelogReady = false;
await Task.Delay(50);
Require(!button.IsEnabled && ViewModel.RelogAvailabilityText.Contains("更新"), "Old plugins must show their real disabled reason.");
ViewModel.PluginRelogReady = true;
await Task.Delay(80);
Require(button.IsEnabled && ViewModel.RelogGameCommand.CanExecute(null), "The actual dashboard button did not enable with the session capability.");
Require(Descendants(button).OfType<TextBlock>().Any(t => t.Text == "返回主菜单并重新进入单人模式"), "The actual mode hint is missing.");
Require(!Descendants(button).OfType<TextBlock>().Any(t => t.Text.Contains("接口验证中")), "The placeholder status survived.");
await CaptureRefinementElementAsync(button, Path.Combine(directory, "ready.png"));
var idle = button.Content;
var originalCommand = AsyncAction.GetCommand(button);
var originalCancel = AsyncAction.GetCancelCommand(button);
var countBefore = Descendants(page).OfType<Button>().Count();
var cancelled = 0;
// Only this synthetic action is run. The production relog command is
// queried above for availability and is never invoked by the probe.
var fake = new AsyncRelayCommand(async token =>
{
try { await Task.Delay(Timeout.Infinite, token); }
catch (OperationCanceledException) { cancelled++; }
});
AsyncAction.SetCommand(button, fake);
AsyncAction.SetCancelCommand(button, new RelayCommand(fake.Cancel));
var operation = fake.ExecuteAsync(null);
await Task.Delay(60);
Require(button.IsEnabled && button.Content as string == "取消", "The same initiating button must remain cancellable.");
Require(Descendants(page).OfType<Button>().Count() == countBefore, "A separate cancel button appeared.");
await CaptureRefinementElementAsync(button, Path.Combine(directory, "cancel.png"));
button.Command.Execute(null);
await operation.WaitAsync(TimeSpan.FromSeconds(2));
await Task.Delay(50);
Require(cancelled == 1 && ReferenceEquals(idle, button.Content), "Cancellation did not restore the original button.");
AsyncAction.SetCommand(button, originalCommand);
AsyncAction.SetCancelCommand(button, originalCancel);
result = new { oldPluginDisabled = true, readyButtonEnabled = true, originalModeHint = true, sameButtonCancellation = true,
cancelled, gameMenuCalls = 0, gameFlightCalls = 0, gameProcessChanges = 0 };
}
catch (Exception error) { failure = error.ToString(); }
await File.WriteAllTextAsync(path, JsonSerializer.Serialize(new { result, failure, offline = true }, new JsonSerializerOptions { WriteIndented = true }));
MainWindow.Close();
}
}