feat: restore legacy modal and drag behavior

This commit is contained in:
2026-07-16 01:33:48 +09:00
parent 83398044c6
commit d7ec571343
30 changed files with 3597 additions and 321 deletions

View File

@@ -289,24 +289,92 @@ public sealed record LegacyConfirmManualListIntent : LegacyUiIntent;
public sealed record LegacyImportManualListsIntent : LegacyUiIntent;
public sealed record LegacyRefreshNamedPlaylistsIntent : LegacyUiIntent;
public sealed record LegacyRefreshNamedPlaylistsIntent(string RequestId) : LegacyUiIntent;
public sealed record LegacySelectNamedPlaylistIntent(string DefinitionId) : LegacyUiIntent;
public sealed record LegacySelectNamedPlaylistIntent(
string DefinitionId,
string RequestId) : LegacyUiIntent;
public sealed record LegacyLoadSelectedNamedPlaylistIntent : LegacyUiIntent;
public sealed record LegacyLoadNamedPlaylistByIdIntent(string DefinitionId) : LegacyUiIntent;
public sealed record LegacyCreateNamedPlaylistIntent(string Title) : LegacyUiIntent;
public sealed record LegacyCreateNamedPlaylistIntent(string Title, string RequestId) : LegacyUiIntent;
public sealed record LegacySaveCurrentNamedPlaylistIntent : LegacyUiIntent;
public sealed record LegacySaveCurrentNamedPlaylistToIntent(string DefinitionId) : LegacyUiIntent;
public sealed record LegacyDeleteSelectedNamedPlaylistIntent : LegacyUiIntent;
public sealed record LegacyDeleteSelectedNamedPlaylistIntent(string RequestId) : LegacyUiIntent;
public sealed record LegacyDismissDialogIntent : LegacyUiIntent;
public sealed record LegacyInteractionMetrics(
int CutDragWidthDips,
int CutDragHeightDips,
uint SourceDpi = 96,
double HostRasterizationScale = 1d)
{
public const uint CssPixelsPerInch = 96;
public const int FallbackCutDragWidth = 4;
public const int FallbackCutDragHeight = 4;
public static LegacyInteractionMetrics Default { get; } = new(
FallbackCutDragWidth,
FallbackCutDragHeight,
CssPixelsPerInch,
1d);
public static LegacyInteractionMetrics FromPixelsAtDpi(
int cutDragWidthPixels,
int cutDragHeightPixels,
uint sourceDpi,
double hostRasterizationScale = 1d) =>
sourceDpi == 0
? Default with
{
HostRasterizationScale = NormalizeHostScale(hostRasterizationScale)
}
: new(
ToDips(
cutDragWidthPixels,
sourceDpi,
FallbackCutDragWidth),
ToDips(
cutDragHeightPixels,
sourceDpi,
FallbackCutDragHeight),
sourceDpi,
NormalizeHostScale(hostRasterizationScale));
internal static LegacyInteractionMetrics Normalize(LegacyInteractionMetrics? metrics) =>
metrics is null
? Default
: new(
metrics.CutDragWidthDips > 0
? metrics.CutDragWidthDips
: FallbackCutDragWidth,
metrics.CutDragHeightDips > 0
? metrics.CutDragHeightDips
: FallbackCutDragHeight,
metrics.SourceDpi > 0 ? metrics.SourceDpi : CssPixelsPerInch,
NormalizeHostScale(metrics.HostRasterizationScale));
private static double NormalizeHostScale(double hostRasterizationScale) =>
double.IsFinite(hostRasterizationScale) && hostRasterizationScale > 0d
? hostRasterizationScale
: 1d;
private static int ToDips(int pixelsAtSourceDpi, uint sourceDpi, int fallback) =>
pixelsAtSourceDpi <= 0
? fallback
: Math.Max(
1,
(int)Math.Round(
pixelsAtSourceDpi * (double)CssPixelsPerInch / sourceDpi,
MidpointRounding.AwayFromZero));
}
public static class LegacyBridgeProtocol
{
public const string TrustedHost = "legacy-parity.mbn.local";
@@ -466,9 +534,7 @@ public static class LegacyBridgeProtocol
"delete-operator-catalog" => ParseOperatorCatalogEmpty(
payload,
static () => new LegacyDeleteOperatorCatalogIntent()),
"refresh-named-playlists" => ParseNamedPlaylistEmpty(
payload,
static () => new LegacyRefreshNamedPlaylistsIntent()),
"refresh-named-playlists" => ParseNamedPlaylistRefresh(payload),
"select-named-playlist" => ParseNamedPlaylistSelection(payload),
"load-named-playlist-by-id" => ParseNamedPlaylistLoadById(payload),
"load-selected-named-playlist" => ParseNamedPlaylistEmpty(
@@ -479,9 +545,8 @@ public static class LegacyBridgeProtocol
payload,
static () => new LegacySaveCurrentNamedPlaylistIntent()),
"save-current-named-playlist-to" => ParseNamedPlaylistSaveTo(payload),
"delete-selected-named-playlist" => ParseNamedPlaylistEmpty(
payload,
static () => new LegacyDeleteSelectedNamedPlaylistIntent()),
"delete-selected-named-playlist" =>
ParseNamedPlaylistDelete(payload),
"open-manual-financial" => ParseManualFinancialOpen(payload),
"close-manual-financial" => ParseManualFinancialEmpty(
payload,
@@ -562,9 +627,12 @@ public static class LegacyBridgeProtocol
public static string SerializeState(
LegacyOperatorSnapshot snapshot,
bool isBusy = false,
LegacyOperatorPlayoutSnapshot? playout = null)
LegacyOperatorPlayoutSnapshot? playout = null,
LegacyInteractionMetrics? interactionMetrics = null)
{
ArgumentNullException.ThrowIfNull(snapshot);
var normalizedInteractionMetrics = LegacyInteractionMetrics.Normalize(
interactionMetrics);
var payload = new
{
snapshot.Revision,
@@ -1057,6 +1125,15 @@ public static class LegacyBridgeProtocol
playout.CanChangeBackground,
playout.Message
},
interactionMetrics = new
{
cutDragWidthDips = normalizedInteractionMetrics.CutDragWidthDips,
cutDragHeightDips = normalizedInteractionMetrics.CutDragHeightDips,
coordinateSpace = "host-dip",
sourceDpi = normalizedInteractionMetrics.SourceDpi,
hostRasterizationScale =
normalizedInteractionMetrics.HostRasterizationScale
},
isBusy
};
@@ -1824,10 +1901,19 @@ public static class LegacyBridgeProtocol
HasOnlyProperties(payload) ? factory() : null;
private static LegacyUiIntent? ParseNamedPlaylistSelection(JsonElement payload) =>
HasOnlyProperties(payload, "definitionId") &&
HasOnlyProperties(payload, "definitionId", "requestId") &&
TryString(payload, "definitionId", 128, out var definitionId) &&
IsSafeIdentifier(definitionId)
? new LegacySelectNamedPlaylistIntent(definitionId)
IsSafeIdentifier(definitionId) &&
TryString(payload, "requestId", 128, out var requestId) &&
IsSafeIdentifier(requestId)
? new LegacySelectNamedPlaylistIntent(definitionId, requestId)
: null;
private static LegacyUiIntent? ParseNamedPlaylistRefresh(JsonElement payload) =>
HasOnlyProperties(payload, "requestId") &&
TryString(payload, "requestId", 128, out var requestId) &&
IsSafeIdentifier(requestId)
? new LegacyRefreshNamedPlaylistsIntent(requestId)
: null;
private static LegacyUiIntent? ParseNamedPlaylistLoadById(JsonElement payload) =>
@@ -1845,7 +1931,7 @@ public static class LegacyBridgeProtocol
: null;
private static LegacyUiIntent? ParseNamedPlaylistCreate(JsonElement payload) =>
HasOnlyProperties(payload, "title") &&
HasOnlyProperties(payload, "title", "requestId") &&
TrySafeString(
payload,
"title",
@@ -1853,8 +1939,17 @@ public static class LegacyBridgeProtocol
allowEmpty: false,
allowUnderscore: true,
out var title) &&
TryString(payload, "requestId", 128, out var requestId) &&
IsSafeIdentifier(requestId) &&
string.Equals(title, title.Trim(), StringComparison.Ordinal)
? new LegacyCreateNamedPlaylistIntent(title)
? new LegacyCreateNamedPlaylistIntent(title, requestId)
: null;
private static LegacyUiIntent? ParseNamedPlaylistDelete(JsonElement payload) =>
HasOnlyProperties(payload, "requestId") &&
TryString(payload, "requestId", 128, out var requestId) &&
IsSafeIdentifier(requestId)
? new LegacyDeleteSelectedNamedPlaylistIntent(requestId)
: null;
private static LegacyUiIntent? ParseManualFinancialOpen(JsonElement payload) =>