fix(persist): one shared z-order across Source + WebcamSceneConfig rows
A webcam dragged between sources reverted to the bottom of the stack on every relaunch: Source and WebcamSceneConfig each carried independent per-type SortOrder counters, and Load appended all Sources before all configs. Save now stamps both tables' SortOrder from the element's index within scene.Elements; Load merges the two tables' rows by that shared z (sources-first tie-break preserves legacy rows). Cross-type reorder now survives a fresh LayoutStore reload. Task 37 queued: defaults vs current layout split (creator directive) — capture out-of-scope work in TASKS.md rather than folding it in.
This commit is contained in:
@@ -11,8 +11,8 @@ public partial class LayoutStore : IDisposable
|
||||
Socials = null;
|
||||
Music = null;
|
||||
var scenes = new List<Scene>();
|
||||
var sourcesByScene = new Dictionary<string, List<Source>>();
|
||||
var configsByScene = new Dictionary<string, List<WebcamSceneConfig>>();
|
||||
var sourcesByScene = new Dictionary<string, List<(Source Source, int Sort)>>();
|
||||
var configsByScene = new Dictionary<string, List<(WebcamSceneConfig Config, int Sort)>>();
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
@@ -99,7 +99,7 @@ public partial class LayoutStore : IDisposable
|
||||
IsBackground, CaptureKey, ShowDesktop,
|
||||
ChatFontSize, ChatFontColor, ChatBackgroundColor, ChatMaxMessages,
|
||||
ChatShowTimestamps, ChatShowBadges, ChatMemberColor, ChatSuperChatColor,
|
||||
WebUri, MediaPath, MediaIsLooping, MediaVolume, MediaPlaybackState
|
||||
WebUri, MediaPath, MediaIsLooping, MediaVolume, MediaPlaybackState, SortOrder
|
||||
FROM Source ORDER BY SortOrder
|
||||
""";
|
||||
using var reader = cmd.ExecuteReader();
|
||||
@@ -147,8 +147,8 @@ public partial class LayoutStore : IDisposable
|
||||
: MediaPlaybackState.Stopped,
|
||||
};
|
||||
if (!sourcesByScene.TryGetValue(sceneId, out var list))
|
||||
sourcesByScene[sceneId] = list = new List<Source>();
|
||||
list.Add(source);
|
||||
sourcesByScene[sceneId] = list = new List<(Source, int)>();
|
||||
list.Add((source, reader.GetInt32(30)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public partial class LayoutStore : IDisposable
|
||||
cmd.CommandText = """
|
||||
SELECT SceneId, WebcamId, IsVisible, X, Y, Width, Height, Opacity,
|
||||
ClipShape, IsMirrored, BorderColor, BorderOpacity, BorderWidth, BorderAnimation,
|
||||
RectWidth, RectHeight
|
||||
RectWidth, RectHeight, SortOrder
|
||||
FROM WebcamSceneConfig ORDER BY SortOrder
|
||||
""";
|
||||
using var reader = cmd.ExecuteReader();
|
||||
@@ -184,19 +184,30 @@ public partial class LayoutStore : IDisposable
|
||||
RectHeight = reader.IsDBNull(15) ? null : reader.GetDouble(15),
|
||||
};
|
||||
if (!configsByScene.TryGetValue(sceneId, out var list))
|
||||
configsByScene[sceneId] = list = new List<WebcamSceneConfig>();
|
||||
list.Add(config);
|
||||
configsByScene[sceneId] = list = new List<(WebcamSceneConfig, int)>();
|
||||
list.Add((config, reader.GetInt32(16)));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var scene in scenes)
|
||||
{
|
||||
// Source and WebcamSceneConfig rows share ONE z-order space per scene
|
||||
// (both SortOrders = the element's index within scene.Elements). Merge
|
||||
// the two tables' rows by that shared z rather than appending all
|
||||
// sources before all configs — a webcam slotted between sources must
|
||||
// reload in place. Legacy rows (written before the unified space) may
|
||||
// tie at 0: break ties sources-first, so old data reads back stacked
|
||||
// the same way it did pre-unification.
|
||||
var ordered = new List<(int Sort, SceneElement Element)>();
|
||||
if (sourcesByScene.TryGetValue(scene.Id, out var sources))
|
||||
foreach (var source in sources)
|
||||
scene.Elements.Add(source);
|
||||
foreach (var (source, sort) in sources)
|
||||
ordered.Add((sort, source));
|
||||
if (configsByScene.TryGetValue(scene.Id, out var configs))
|
||||
foreach (var config in configs)
|
||||
scene.Elements.Add(config);
|
||||
foreach (var (config, sort) in configs)
|
||||
ordered.Add((sort, config));
|
||||
|
||||
foreach (var (_, element) in ordered.OrderBy(e => e.Sort).ThenBy(e => e.Element is Source ? 0 : 1))
|
||||
scene.Elements.Add(element);
|
||||
|
||||
var bg = scene.Elements.OfType<Source>().FirstOrDefault(s => s.IsBackground);
|
||||
if (bg != null)
|
||||
|
||||
Reference in New Issue
Block a user