feat: advance legacy UI behavior parity
This commit is contained in:
@@ -82,6 +82,10 @@ public sealed record LegacyActivateFixedSectionIntent(int SectionIndex) : Legacy
|
||||
|
||||
public sealed record LegacySelectIndustryIntent(int Index, bool DoubleClick) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySetIndustryComparisonTextIntent(
|
||||
LegacyIndustryComparisonSlot Slot,
|
||||
string Value) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySwapIndustriesIntent : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyActivateIndustryActionIntent(string ActionId) : LegacyUiIntent;
|
||||
@@ -135,7 +139,9 @@ public sealed record LegacyActivateComparisonActionIntent(string ActionId) : Leg
|
||||
|
||||
public sealed record LegacyActivateComparisonSectionIntent(int SectionIndex) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySearchThemesIntent(string Query, ThemeSession NxtSession)
|
||||
// UC4 has no NXT-session control. The native controller chooses it from its
|
||||
// local clock, so the WebView can supply only the search text.
|
||||
public sealed record LegacySearchThemesIntent(string Query)
|
||||
: LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySelectThemeIntent(string ResultId) : LegacyUiIntent;
|
||||
@@ -207,15 +213,23 @@ public sealed record LegacyReorderOperatorCatalogDraftRowIntent(
|
||||
|
||||
public sealed record LegacyRemoveOperatorCatalogDraftRowIntent(string RowId) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySelectOperatorCatalogDraftRowIntent(string RowId) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyRemoveActiveOperatorCatalogDraftRowIntent : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyClearOperatorCatalogDraftRowsIntent : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySetOperatorCatalogDraftBuyAmountIntent(
|
||||
string RowId,
|
||||
decimal BuyAmount) : LegacyUiIntent;
|
||||
decimal? BuyAmount) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyCheckOperatorCatalogThemeNameIntent(string Name) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacySaveOperatorCatalogIntent(string Name) : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyDeleteOperatorCatalogIntent : LegacyUiIntent;
|
||||
public sealed record LegacyConfirmNativeDialogIntent : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyCancelNativeDialogIntent : LegacyUiIntent;
|
||||
|
||||
public sealed record LegacyOpenManualFinancialIntent(ManualFinancialScreenKind Screen)
|
||||
: LegacyUiIntent;
|
||||
@@ -447,6 +461,7 @@ public static class LegacyBridgeProtocol
|
||||
"activate-fixed-section" => ParseFixedSection(payload),
|
||||
"select-industry" => ParseIndustrySelection(payload, false),
|
||||
"double-click-industry" => ParseIndustrySelection(payload, true),
|
||||
"set-industry-comparison-text" => ParseIndustryComparisonText(payload),
|
||||
"swap-industries" => ParseSwapIndustries(payload),
|
||||
"activate-industry-action" => ParseIndustryAction(payload),
|
||||
"activate-industry-section" => ParseSectionIndex(
|
||||
@@ -526,14 +541,25 @@ public static class LegacyBridgeProtocol
|
||||
"reorder-operator-catalog-draft-row" =>
|
||||
ParseOperatorCatalogDraftReorder(payload),
|
||||
"remove-operator-catalog-draft-row" => ParseOperatorCatalogDraftRemove(payload),
|
||||
"select-operator-catalog-draft-row" =>
|
||||
ParseOperatorCatalogDraftSelection(payload),
|
||||
"remove-active-operator-catalog-draft-row" => ParseOperatorCatalogEmpty(
|
||||
payload,
|
||||
static () => new LegacyRemoveActiveOperatorCatalogDraftRowIntent()),
|
||||
"clear-operator-catalog-draft-rows" => ParseOperatorCatalogEmpty(
|
||||
payload,
|
||||
static () => new LegacyClearOperatorCatalogDraftRowsIntent()),
|
||||
"set-operator-catalog-draft-buy-amount" =>
|
||||
ParseOperatorCatalogDraftBuyAmount(payload),
|
||||
"check-operator-catalog-theme-name" =>
|
||||
ParseOperatorCatalogThemeNameCheck(payload),
|
||||
"save-operator-catalog" => ParseOperatorCatalogSave(payload),
|
||||
"delete-operator-catalog" => ParseOperatorCatalogEmpty(
|
||||
"confirm-native-dialog" => ParseOperatorCatalogEmpty(
|
||||
payload,
|
||||
static () => new LegacyDeleteOperatorCatalogIntent()),
|
||||
static () => new LegacyConfirmNativeDialogIntent()),
|
||||
"cancel-native-dialog" => ParseOperatorCatalogEmpty(
|
||||
payload,
|
||||
static () => new LegacyCancelNativeDialogIntent()),
|
||||
"refresh-named-playlists" => ParseNamedPlaylistRefresh(payload),
|
||||
"select-named-playlist" => ParseNamedPlaylistSelection(payload),
|
||||
"load-named-playlist-by-id" => ParseNamedPlaylistLoadById(payload),
|
||||
@@ -676,8 +702,8 @@ public static class LegacyBridgeProtocol
|
||||
}),
|
||||
snapshot.Industry.SelectedIndex,
|
||||
selectedName = snapshot.Industry.SelectedIndustry?.IndustryName,
|
||||
firstName = snapshot.Industry.FirstIndustry?.IndustryName,
|
||||
secondName = snapshot.Industry.SecondIndustry?.IndustryName,
|
||||
firstName = snapshot.Industry.FirstText,
|
||||
secondName = snapshot.Industry.SecondText,
|
||||
actions = snapshot.Industry.Actions.Select(action => new
|
||||
{
|
||||
actionId = action.ActionId,
|
||||
@@ -723,27 +749,22 @@ public static class LegacyBridgeProtocol
|
||||
results = snapshot.Overseas.Stock.Results.Select(row => new
|
||||
{
|
||||
row.SelectionId,
|
||||
displayName = row.InputName,
|
||||
row.NationCode
|
||||
displayName = row.InputName
|
||||
})
|
||||
},
|
||||
actions = snapshot.Overseas.Actions.Select(action => new
|
||||
actions = snapshot.Overseas.Actions.Select(action =>
|
||||
{
|
||||
action.ActionId,
|
||||
action.Label,
|
||||
action.Source,
|
||||
action.Kind,
|
||||
action.PeriodDays,
|
||||
isAvailable = action.Source switch
|
||||
var availability = GetOverseasActionAvailability(snapshot.Overseas, action);
|
||||
return new
|
||||
{
|
||||
LegacyOverseasActionSource.FixedIndex =>
|
||||
snapshot.Overseas.SelectedFixedIndex is not null,
|
||||
LegacyOverseasActionSource.Industry =>
|
||||
snapshot.Overseas.Industry.Selected is not null,
|
||||
LegacyOverseasActionSource.Stock =>
|
||||
snapshot.Overseas.Stock.Selected is not null,
|
||||
_ => false
|
||||
}
|
||||
action.ActionId,
|
||||
action.Label,
|
||||
action.Source,
|
||||
action.Kind,
|
||||
action.PeriodDays,
|
||||
availability.IsAvailable,
|
||||
availability.Reason
|
||||
};
|
||||
})
|
||||
},
|
||||
comparison = snapshot.Comparison is null ? null : new
|
||||
@@ -946,6 +967,7 @@ public static class LegacyBridgeProtocol
|
||||
row.BuyAmount,
|
||||
row.Position
|
||||
}),
|
||||
snapshot.OperatorCatalog.ActiveDraftRowId,
|
||||
snapshot.OperatorCatalog.StockQuery,
|
||||
stockResults = snapshot.OperatorCatalog.StockResults.Select(row => new
|
||||
{
|
||||
@@ -1119,6 +1141,9 @@ public static class LegacyBridgeProtocol
|
||||
playout.RefreshCompletedCount,
|
||||
playout.RefreshMaximumCount,
|
||||
playout.RefreshLimitReached,
|
||||
playout.RefreshNextAtUtc,
|
||||
playout.RefreshLastSuccessAtUtc,
|
||||
playout.RefreshFaultCode,
|
||||
playout.FadeDuration,
|
||||
playout.BackgroundEnabled,
|
||||
playout.BackgroundFileName,
|
||||
@@ -1140,6 +1165,22 @@ public static class LegacyBridgeProtocol
|
||||
return JsonSerializer.Serialize(new { type = "state", payload }, SerializerOptions);
|
||||
}
|
||||
|
||||
private static LegacyOverseasActionAvailability GetOverseasActionAvailability(
|
||||
LegacyOverseasWorkflowSnapshot snapshot,
|
||||
LegacyOverseasActionDefinition action) =>
|
||||
action.Source switch
|
||||
{
|
||||
LegacyOverseasActionSource.FixedIndex when snapshot.SelectedFixedIndex is null =>
|
||||
new(false, "해외지수를 선택하십시오."),
|
||||
LegacyOverseasActionSource.Industry when snapshot.Industry.Selected is null =>
|
||||
new(false, "해외업종을 선택하십시오."),
|
||||
LegacyOverseasActionSource.Stock when snapshot.Stock.Selected is null =>
|
||||
new(false, "해외종목을 선택하십시오."),
|
||||
LegacyOverseasActionSource.Stock when snapshot.Stock.Selected!.NationCode.Length != 2 =>
|
||||
new(false, "선택한 해외종목의 국가 코드는 두 글자여야 합니다."),
|
||||
_ => new(true, null)
|
||||
};
|
||||
|
||||
private static LegacyUiIntent? ParseReady(JsonElement payload) =>
|
||||
HasOnlyProperties(payload) ? new LegacyReadyIntent() : null;
|
||||
|
||||
@@ -1400,6 +1441,32 @@ public static class LegacyBridgeProtocol
|
||||
? new LegacySelectIndustryIntent(index, doubleClick)
|
||||
: null;
|
||||
|
||||
private static LegacyUiIntent? ParseIndustryComparisonText(JsonElement payload)
|
||||
{
|
||||
if (!HasOnlyProperties(payload, "slot", "value") ||
|
||||
!TryString(payload, "slot", 16, out var slotText) ||
|
||||
!TrySafeString(
|
||||
payload,
|
||||
"value",
|
||||
LegacyIndustrySelectionWorkflow.MaximumComparisonTextLength,
|
||||
allowEmpty: true,
|
||||
allowUnderscore: true,
|
||||
out var value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var slot = slotText switch
|
||||
{
|
||||
"first" => LegacyIndustryComparisonSlot.First,
|
||||
"second" => LegacyIndustryComparisonSlot.Second,
|
||||
_ => (LegacyIndustryComparisonSlot?)null
|
||||
};
|
||||
return slot.HasValue
|
||||
? new LegacySetIndustryComparisonTextIntent(slot.Value, value)
|
||||
: null;
|
||||
}
|
||||
|
||||
private static LegacyUiIntent? ParseSwapIndustries(JsonElement payload) =>
|
||||
HasOnlyProperties(payload) ? new LegacySwapIndustriesIntent() : null;
|
||||
|
||||
@@ -1556,26 +1623,17 @@ public static class LegacyBridgeProtocol
|
||||
|
||||
private static LegacyUiIntent? ParseThemeSearch(JsonElement payload)
|
||||
{
|
||||
if (!HasOnlyProperties(payload, "query", "nxtSession") ||
|
||||
if (!HasOnlyProperties(payload, "query") ||
|
||||
!TryString(
|
||||
payload,
|
||||
"query",
|
||||
LegacyThemeSelectionService.MaximumQueryLength,
|
||||
out var query) ||
|
||||
!TryString(payload, "nxtSession", 16, out var sessionText))
|
||||
out var query))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var session = sessionText switch
|
||||
{
|
||||
"preMarket" => ThemeSession.PreMarket,
|
||||
"afterMarket" => ThemeSession.AfterMarket,
|
||||
_ => (ThemeSession?)null
|
||||
};
|
||||
return session.HasValue
|
||||
? new LegacySearchThemesIntent(query, session.Value)
|
||||
: null;
|
||||
return new LegacySearchThemesIntent(query);
|
||||
}
|
||||
|
||||
private static LegacyUiIntent? ParseThemeSelection(JsonElement payload) =>
|
||||
@@ -1857,17 +1915,35 @@ public static class LegacyBridgeProtocol
|
||||
? new LegacyRemoveOperatorCatalogDraftRowIntent(rowId)
|
||||
: null;
|
||||
|
||||
private static LegacyUiIntent? ParseOperatorCatalogDraftBuyAmount(JsonElement payload) =>
|
||||
HasOnlyProperties(payload, "rowId", "buyAmount") &&
|
||||
private static LegacyUiIntent? ParseOperatorCatalogDraftSelection(JsonElement payload) =>
|
||||
HasOnlyProperties(payload, "rowId") &&
|
||||
TryString(payload, "rowId", 128, out var rowId) &&
|
||||
IsSafeIdentifier(rowId) &&
|
||||
payload.TryGetProperty("buyAmount", out var amountElement) &&
|
||||
amountElement.ValueKind == JsonValueKind.Number &&
|
||||
amountElement.TryGetDecimal(out var amount) &&
|
||||
decimal.Truncate(amount) == amount &&
|
||||
amount is > 0 and <= 9_007_199_254_740_991m
|
||||
IsSafeIdentifier(rowId)
|
||||
? new LegacySelectOperatorCatalogDraftRowIntent(rowId)
|
||||
: null;
|
||||
|
||||
private static LegacyUiIntent? ParseOperatorCatalogDraftBuyAmount(JsonElement payload)
|
||||
{
|
||||
if (!HasOnlyProperties(payload, "rowId", "buyAmount") ||
|
||||
!TryString(payload, "rowId", 128, out var rowId) ||
|
||||
!IsSafeIdentifier(rowId) ||
|
||||
!payload.TryGetProperty("buyAmount", out var amountElement))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (amountElement.ValueKind == JsonValueKind.Null)
|
||||
{
|
||||
return new LegacySetOperatorCatalogDraftBuyAmountIntent(rowId, null);
|
||||
}
|
||||
|
||||
return amountElement.ValueKind == JsonValueKind.Number &&
|
||||
amountElement.TryGetDecimal(out var amount) &&
|
||||
decimal.Truncate(amount) == amount &&
|
||||
amount is > 0 and <= 9_007_199_254_740_991m
|
||||
? new LegacySetOperatorCatalogDraftBuyAmountIntent(rowId, amount)
|
||||
: null;
|
||||
}
|
||||
|
||||
private static LegacyUiIntent? ParseOperatorCatalogSave(JsonElement payload) =>
|
||||
HasOnlyProperties(payload, "name") &&
|
||||
@@ -1875,7 +1951,7 @@ public static class LegacyBridgeProtocol
|
||||
payload,
|
||||
"name",
|
||||
128,
|
||||
allowEmpty: false,
|
||||
allowEmpty: true,
|
||||
allowUnderscore: true,
|
||||
out var name) &&
|
||||
string.Equals(name, name.Trim(), StringComparison.Ordinal)
|
||||
|
||||
Reference in New Issue
Block a user