Control Surface UX: pill toggle, background rename, per-scene properties
- Sliding pill toggle (green ON / red OFF) replaces checkbox - Geometry mismatch error for custom backgrounds - Backdrop -> Background: C# rename, SQL column rename with migration - Source.IsBackground: new -> override (fixes WPF binding) - Legacy 'Backdrop' display name migrated to 'Background' - Per-scene UseDefaultBackground + CustomBackgroundPath - Asset files renamed backdrop -> background - StagedScene/LiveScene split, thumbnail strip, edit gating - TransitionService (Cut/Fade/Move) - Context menu: Capture Desktop, Refresh Desktop - Resolution badge removed, ON-AIR status light added
This commit is contained in:
@@ -78,21 +78,21 @@ public class LayoutStorePersistenceTests
|
||||
}
|
||||
}
|
||||
|
||||
// The backdrop (schema v5): permanent bottom layer holding live desktop/game
|
||||
// capture. IsBackdrop + CaptureKey must survive a save + reload so a
|
||||
// The background (schema v5): permanent bottom layer holding live desktop/game
|
||||
// capture. IsBackground + CaptureKey must survive a save + reload so a
|
||||
// re-designated target isn't lost on restart.
|
||||
[Fact]
|
||||
public void Backdrop_IsBackdrop_And_CaptureKey_Survive_Save_And_Reload()
|
||||
public void Background_IsBackground_And_CaptureKey_Survive_Save_And_Reload()
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-{Guid.NewGuid():N}.db");
|
||||
try
|
||||
{
|
||||
using var store = new LayoutStore(path);
|
||||
var backdrop = new Source
|
||||
var background = new Source
|
||||
{
|
||||
Name = "Game Capture",
|
||||
Type = SourceType.DisplayCapture,
|
||||
IsBackdrop = true,
|
||||
IsBackground = true,
|
||||
IsEnabled = true,
|
||||
X = 0,
|
||||
Y = 0,
|
||||
@@ -102,13 +102,13 @@ public class LayoutStorePersistenceTests
|
||||
CaptureKey = "monitor:1",
|
||||
};
|
||||
var scene = new Scene { Name = "Starting" };
|
||||
scene.Elements.Add(backdrop);
|
||||
scene.Elements.Add(background);
|
||||
store.Save(new[] { scene }, null, null);
|
||||
|
||||
var reloaded = store.Load();
|
||||
var restored = Assert.IsType<Source>(Assert.Single(reloaded[0].Elements));
|
||||
|
||||
Assert.True(restored.IsBackdrop);
|
||||
Assert.True(restored.IsBackground);
|
||||
Assert.Equal("monitor:1", restored.CaptureKey);
|
||||
Assert.Equal(1, restored.MonitorIndex);
|
||||
Assert.Equal(SourceType.DisplayCapture, restored.Type);
|
||||
@@ -120,23 +120,23 @@ public class LayoutStorePersistenceTests
|
||||
}
|
||||
}
|
||||
|
||||
// Per-scene backdrop switch (schema v6): a scene whose backdrop was turned
|
||||
// Per-scene background switch (schema v6): a scene whose background was turned
|
||||
// off must stay off across a save + reload.
|
||||
[Fact]
|
||||
public void Scene_HasBackdrop_Survives_Save_And_Reload()
|
||||
public void Scene_HasBackground_Survives_Save_And_Reload()
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-{Guid.NewGuid():N}.db");
|
||||
try
|
||||
{
|
||||
using var store = new LayoutStore(path);
|
||||
var on = new Scene { Name = "Live", HasBackdrop = true };
|
||||
var off = new Scene { Name = "Ending", HasBackdrop = false };
|
||||
var on = new Scene { Name = "Live", HasBackground = true };
|
||||
var off = new Scene { Name = "Ending", HasBackground = false };
|
||||
store.Save(new[] { on, off }, null, null);
|
||||
|
||||
var reloaded = store.Load();
|
||||
|
||||
Assert.True(reloaded.First(s => s.Name == "Live").HasBackdrop);
|
||||
Assert.False(reloaded.First(s => s.Name == "Ending").HasBackdrop);
|
||||
Assert.True(reloaded.First(s => s.Name == "Live").HasBackground);
|
||||
Assert.False(reloaded.First(s => s.Name == "Ending").HasBackground);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -145,12 +145,12 @@ public class LayoutStorePersistenceTests
|
||||
}
|
||||
}
|
||||
|
||||
// v5 → v6 one-time backfill: pre-v6 DBs already have backdrops sitting in the
|
||||
// non-Live canonical scenes (Starting/BRB/Chat/Ending). Adding the HasBackdrop
|
||||
// column turns those scenes off and drops their backdrop sources; Live keeps
|
||||
// its backdrop.
|
||||
// v5 → v6 one-time backfill: pre-v6 DBs already have backgrounds sitting in the
|
||||
// non-Live canonical scenes (Starting/BRB/Chat/Ending). Adding the HasBackground
|
||||
// column turns those scenes off and drops their background sources; Live keeps
|
||||
// its background.
|
||||
[Fact]
|
||||
public void V5_Database_Backfill_Removes_NonLive_Backdrops()
|
||||
public void V5_Database_Backfill_Removes_NonLive_Backgrounds()
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-{Guid.NewGuid():N}.db");
|
||||
try
|
||||
@@ -183,19 +183,19 @@ public class LayoutStorePersistenceTests
|
||||
DeviceId TEXT,
|
||||
ClipShape TEXT NOT NULL DEFAULT 'Traditional',
|
||||
IsMirrored INTEGER NOT NULL DEFAULT 0,
|
||||
IsBackdrop INTEGER NOT NULL DEFAULT 0,
|
||||
IsBackground INTEGER NOT NULL DEFAULT 0,
|
||||
CaptureKey TEXT,
|
||||
SortOrder INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
INSERT INTO Scene (Id, Name, SortOrder) VALUES ('s-starting', 'Starting', 0);
|
||||
INSERT INTO Scene (Id, Name, SortOrder) VALUES ('s-live', 'Live', 1);
|
||||
INSERT INTO Scene (Id, Name, SortOrder) VALUES ('s-chat', 'Chat', 2);
|
||||
INSERT INTO Source (Id, SceneId, Type, Name, IsBackdrop, CaptureKey, SortOrder)
|
||||
VALUES ('b-starting', 's-starting', 'DisplayCapture', 'Backdrop', 1, 'monitor:0', 0);
|
||||
INSERT INTO Source (Id, SceneId, Type, Name, IsBackdrop, CaptureKey, SortOrder)
|
||||
VALUES ('b-live', 's-live', 'DisplayCapture', 'Backdrop', 1, 'monitor:0', 0);
|
||||
INSERT INTO Source (Id, SceneId, Type, Name, IsBackdrop, CaptureKey, SortOrder)
|
||||
VALUES ('b-chat', 's-chat', 'DisplayCapture', 'Backdrop', 1, 'monitor:0', 0);
|
||||
INSERT INTO Source (Id, SceneId, Type, Name, IsBackground, CaptureKey, SortOrder)
|
||||
VALUES ('b-starting', 's-starting', 'DisplayCapture', 'Background', 1, 'monitor:0', 0);
|
||||
INSERT INTO Source (Id, SceneId, Type, Name, IsBackground, CaptureKey, SortOrder)
|
||||
VALUES ('b-live', 's-live', 'DisplayCapture', 'Background', 1, 'monitor:0', 0);
|
||||
INSERT INTO Source (Id, SceneId, Type, Name, IsBackground, CaptureKey, SortOrder)
|
||||
VALUES ('b-chat', 's-chat', 'DisplayCapture', 'Background', 1, 'monitor:0', 0);
|
||||
PRAGMA user_version = 5;
|
||||
""";
|
||||
cmd.ExecuteNonQuery();
|
||||
@@ -205,16 +205,16 @@ public class LayoutStorePersistenceTests
|
||||
var scenes = store.Load();
|
||||
|
||||
var starting = Assert.Single(scenes, s => s.Name == "Starting");
|
||||
Assert.False(starting.HasBackdrop);
|
||||
Assert.DoesNotContain(starting.Elements, e => e is Source { IsBackdrop: true });
|
||||
Assert.False(starting.HasBackground);
|
||||
Assert.DoesNotContain(starting.Elements, e => e is Source { IsBackground: true });
|
||||
|
||||
var chat = Assert.Single(scenes, s => s.Name == "Chat");
|
||||
Assert.False(chat.HasBackdrop);
|
||||
Assert.DoesNotContain(chat.Elements, e => e is Source { IsBackdrop: true });
|
||||
Assert.False(chat.HasBackground);
|
||||
Assert.DoesNotContain(chat.Elements, e => e is Source { IsBackground: true });
|
||||
|
||||
var live = Assert.Single(scenes, s => s.Name == "Live");
|
||||
Assert.True(live.HasBackdrop);
|
||||
Assert.Single(live.Elements, e => e is Source { IsBackdrop: true });
|
||||
Assert.True(live.HasBackground);
|
||||
Assert.Single(live.Elements, e => e is Source { IsBackground: true });
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user