feat: advance legacy UI behavior parity

This commit is contained in:
2026-07-18 10:18:29 +09:00
parent d7ec571343
commit 1302b1b92f
71 changed files with 11244 additions and 1153 deletions

View File

@@ -58,6 +58,7 @@ public sealed partial class MainWindow : Window
IExpertSelectionService expertSelectionService;
ITradingHaltSelectionService tradingHaltSelectionService;
IOverseasIndustryIndexSearchService overseasIndustrySearchService;
IOverseasStockSearchService overseasStockSearchService;
IWorldStockSearchService worldStockSearchService;
IManualFinancialScreenService manualFinancialService;
IStockSearchService manualFinancialStockSearchService;
@@ -82,6 +83,8 @@ public sealed partial class MainWindow : Window
_databaseRuntime.Executor);
overseasIndustrySearchService = new LegacyOverseasIndustryIndexSearchService(
_databaseRuntime.Executor);
overseasStockSearchService = new LegacyOverseasStockSearchService(
_databaseRuntime.Executor);
worldStockSearchService = new LegacyWorldStockSearchService(
_databaseRuntime.Executor);
manualFinancialService = new LegacyManualFinancialScreenService(
@@ -125,6 +128,8 @@ public sealed partial class MainWindow : Window
initializationError);
overseasIndustrySearchService = new UnavailableOverseasIndustryIndexSearchService(
initializationError);
overseasStockSearchService = new UnavailableOverseasStockSearchService(
initializationError);
worldStockSearchService = new UnavailableWorldStockSearchService(
initializationError);
manualFinancialService = new UnavailableManualFinancialScreenService(
@@ -147,7 +152,7 @@ public sealed partial class MainWindow : Window
_industryWorkflow = new LegacyIndustrySelectionWorkflow(industrySelectionService);
var overseasWorkflow = new LegacyOverseasSelectionWorkflow(
overseasIndustrySearchService,
worldStockSearchService);
overseasStockSearchService);
var comparisonStore = new LegacyComparisonPairFileStore(
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
@@ -372,6 +377,18 @@ public sealed partial class MainWindow : Window
return;
}
if (_controller.Current.Dialog?.IsConfirmation == true &&
intent is not LegacyReadyIntent and
not LegacyConfirmNativeDialogIntent and
not LegacyCancelNativeDialogIntent)
{
// A native MessageBox is modal in the original application. Ignore
// every forged or already-posted background intent until the
// operator answers the currently visible Yes/No question.
PostState(_controller.Current);
return;
}
if (IsOperatorMutationIntent(intent) && IsOperatorMutationQuarantined())
{
PostState(ReportIntentFailure(
@@ -413,10 +430,8 @@ public sealed partial class MainWindow : Window
LegacyOpenOperatorCatalogIntent or
LegacyBeginUc4ThemeCatalogIntent or
LegacyEditUc4SelectedThemeIntent or
LegacyDeleteUc4SelectedThemeIntent or
LegacyBeginUc6ExpertCatalogIntent or
LegacyEditUc6SelectedExpertIntent or
LegacyDeleteUc6SelectedExpertIntent or
LegacySearchOperatorCatalogIntent or
LegacySelectOperatorCatalogResultIntent or
LegacyBeginCreateThemeCatalogIntent or
@@ -426,7 +441,7 @@ public sealed partial class MainWindow : Window
LegacySetOperatorCatalogDraftBuyAmountIntent or
LegacyCheckOperatorCatalogThemeNameIntent or
LegacySaveOperatorCatalogIntent or
LegacyDeleteOperatorCatalogIntent or
LegacyConfirmNativeDialogIntent or
LegacyAddComparisonPairIntent or
LegacyMoveComparisonPairIntent or
LegacyDeleteSelectedComparisonPairIntent or
@@ -655,6 +670,8 @@ public sealed partial class MainWindow : Window
cancellationToken),
LegacySelectIndustryIntent industry =>
_controller.SelectIndustry(industry.Index, industry.DoubleClick),
LegacySetIndustryComparisonTextIntent edit =>
_controller.SetIndustryComparisonText(edit.Slot, edit.Value),
LegacySwapIndustriesIntent =>
_controller.SwapIndustries(),
LegacyActivateIndustryActionIntent action =>
@@ -724,7 +741,6 @@ public sealed partial class MainWindow : Window
LegacySearchThemesIntent search =>
await _controller.SearchThemesAsync(
search.Query,
search.NxtSession,
cancellationToken),
LegacySelectThemeIntent selection =>
await _controller.SelectThemeAsync(
@@ -773,7 +789,7 @@ public sealed partial class MainWindow : Window
LegacyDeleteUc6SelectedExpertIntent =>
await _controller.DeleteSelectedExpertCatalogAsync(cancellationToken),
LegacyCloseOperatorCatalogIntent =>
_controller.CloseOperatorCatalog(),
await _controller.CloseOperatorCatalogAsync(cancellationToken),
LegacySearchOperatorCatalogIntent search =>
await _controller.SearchOperatorCatalogAsync(
search.Query,
@@ -810,6 +826,12 @@ public sealed partial class MainWindow : Window
reorder.Position),
LegacyRemoveOperatorCatalogDraftRowIntent remove =>
_controller.RemoveOperatorCatalogDraftRow(remove.RowId),
LegacySelectOperatorCatalogDraftRowIntent selection =>
_controller.SelectOperatorCatalogDraftRow(selection.RowId),
LegacyRemoveActiveOperatorCatalogDraftRowIntent =>
_controller.RemoveActiveOperatorCatalogDraftRow(),
LegacyClearOperatorCatalogDraftRowsIntent =>
_controller.ClearOperatorCatalogDraftRows(),
LegacySetOperatorCatalogDraftBuyAmountIntent amount =>
_controller.SetOperatorCatalogDraftBuyAmount(
amount.RowId,
@@ -822,8 +844,10 @@ public sealed partial class MainWindow : Window
await _controller.SaveOperatorCatalogAsync(
save.Name,
cancellationToken),
LegacyDeleteOperatorCatalogIntent =>
await _controller.DeleteOperatorCatalogAsync(cancellationToken),
LegacyConfirmNativeDialogIntent =>
await _controller.ConfirmDialogAsync(cancellationToken),
LegacyCancelNativeDialogIntent =>
_controller.CancelDialog(),
LegacyRefreshNamedPlaylistsIntent refresh =>
await RefreshNamedPlaylistsForDispatchAsync(
refresh.RequestId,
@@ -1611,6 +1635,23 @@ public sealed partial class MainWindow : Window
Task.FromException<StockSearchResult>(new InvalidOperationException(_message));
}
private sealed class UnavailableOverseasStockSearchService : IOverseasStockSearchService
{
private readonly string _message;
public UnavailableOverseasStockSearchService(string message)
{
_message = message;
}
public Task<WorldStockSearchResult> SearchAsync(
string query,
int maximumResults = LegacyOverseasStockSearchService.DefaultMaximumResults,
CancellationToken cancellationToken = default) =>
Task.FromException<WorldStockSearchResult>(
new InvalidOperationException(_message));
}
private sealed class UnavailableWorldStockSearchService : IWorldStockSearchService
{
private readonly string _message;