From 0ed341fd1863629c31945018ab3ea3e59b6ce084 Mon Sep 17 00:00:00 2001 From: gramps Date: Sun, 1 Nov 2026 13:08:03 -0800 Subject: [PATCH] =?UTF-8?q?fix(blur):=20the=20crash=20on=20launch=20?= =?UTF-8?q?=E2=80=94=20BlurAmount=20was=20in=20the=20INSERT=20and=20the=20?= =?UTF-8?q?reader,=20not=20the=20SELECT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LayoutStore.Load threw ArgumentOutOfRangeException on GetOrdinal("BlurAmount") during the MainViewModel constructor, so the app died at startup rather than when a blur was used. The migration adds the column and Save writes it; the reading query still listed its columns explicitly and BlurAmount was missing from that list. Adds LayoutBlurPersistenceTests: a blur saved and reloaded, asserting the amount and geometry survive. That is the test that should have existed with the feature — the startup path it covers has no other guard. --- Services/LayoutStore.Load.cs | 2 +- ytLive.Tests/LayoutBlurPersistenceTests.cs | 50 ++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 ytLive.Tests/LayoutBlurPersistenceTests.cs diff --git a/Services/LayoutStore.Load.cs b/Services/LayoutStore.Load.cs index 8775c9b..22cfdb4 100644 --- a/Services/LayoutStore.Load.cs +++ b/Services/LayoutStore.Load.cs @@ -111,7 +111,7 @@ public partial class LayoutStore : IDisposable ChatShowTimestamps, ChatShowBadges, ChatMemberColor, ChatSuperChatColor, WebUri, MediaPath, MediaIsLooping, MediaVolume, MediaPlaybackState, AlertVideoAssetId, AlertVideoPath, AlertUseDefaultVideo, AlertShowTicker, AlertVideoVolume, SortOrder, - AlertDisplayMethod, IsBrandLogo + AlertDisplayMethod, IsBrandLogo, BlurAmount FROM Source ORDER BY SortOrder """; using var reader = cmd.ExecuteReader(); diff --git a/ytLive.Tests/LayoutBlurPersistenceTests.cs b/ytLive.Tests/LayoutBlurPersistenceTests.cs new file mode 100644 index 0000000..c5dae1f --- /dev/null +++ b/ytLive.Tests/LayoutBlurPersistenceTests.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using Xunit; +using ytLive.Models; +using ytLive.Services; + +namespace ytLive.Tests; + +/// +/// The blur column round-trips through SQLite (2026-11-01). This exists because the first cut +/// added `BlurAmount` to the INSERT and the reader but not to the SELECT — the app then crashed on +/// launch inside `GetOrdinal("BlurAmount")`, which is a startup path no other test covers. +/// +public class LayoutBlurPersistenceTests +{ + [Fact] + public void A_blur_layer_survives_a_save_and_reload_with_its_amount() + { + var dbPath = Path.Combine(Path.GetTempPath(), $"llamacasty-blur-{Guid.NewGuid():N}.db"); + try + { + var scenes = new ObservableCollection + { + new() { Name = SceneCatalog.Live }, + }; + var background = new Source { Name = "Background", Type = SourceType.Background, IsBackground = true, Width = 1920, Height = 1080 }; + var blur = new Source { Name = "Blur", Type = SourceType.Blur, X = 40, Y = 50, Width = 240, Height = 160, BlurAmount = 0.8 }; + scenes[0].Elements.Add(background); + scenes[0].Elements.Add(blur); + + using (var store = new LayoutStore(dbPath)) + store.Save(scenes, null, null); + + using (var reopened = new LayoutStore(dbPath)) + { + var loaded = reopened.Load(); + var loadedBlur = loaded.SelectMany(s => s.Elements).OfType().Single(s => s.Type == SourceType.Blur); + Assert.Equal(0.8, loadedBlur.BlurAmount, 3); + Assert.Equal(240, loadedBlur.Width, 3); + Assert.Equal(SourceType.Blur, loadedBlur.Type); + } + } + finally + { + try { File.Delete(dbPath); } catch (IOException) { } + } + } +}