diff --git a/src/LageBuch.App/Services/SerialAudioQueue.cs b/src/LageBuch.App/Services/SerialAudioQueue.cs index a3fa57d..44f520c 100644 --- a/src/LageBuch.App/Services/SerialAudioQueue.cs +++ b/src/LageBuch.App/Services/SerialAudioQueue.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; namespace LageBuch.App.Services; @@ -11,7 +12,9 @@ namespace LageBuch.App.Services; /// audio player process that never exits), the queue moves on to the next item anyway so one /// stuck cue can't permanently silence later ones. /// -public sealed class SerialAudioQueue +[SuppressMessage("Design", "CA1001", + Justification = "App-lifetime singleton: its worker thread drains until process shutdown, so the owning BlockingCollection is intentionally never disposed.")] +internal sealed class SerialAudioQueue { private readonly BlockingCollection _queue = new(); private readonly TimeSpan _perItemTimeout; @@ -26,6 +29,8 @@ public SerialAudioQueue(TimeSpan? perItemTimeout = null) /// Queues to run after everything already queued. public void Enqueue(Action play) => _queue.Add(play); + [SuppressMessage("Design", "CA1031", + Justification = "A misbehaving or hanging cue must not stop the worker from serving the next one (the per-item timeout has already elapsed).")] private void Run() { foreach (var play in _queue.GetConsumingEnumerable()) diff --git a/src/LageBuch.App/Services/SystemAlarmService.cs b/src/LageBuch.App/Services/SystemAlarmService.cs index f316b09..0498592 100644 --- a/src/LageBuch.App/Services/SystemAlarmService.cs +++ b/src/LageBuch.App/Services/SystemAlarmService.cs @@ -55,6 +55,8 @@ public void Play(AlarmSound sound) } // Runs on the SerialAudioQueue's worker thread; blocks until the clip finishes playing. + [SuppressMessage("Design", "CA1031", + Justification = "Player binary missing (e.g. a headless Linux host without ALSA) — stay silent.")] private void PlayBlocking(AlarmSound sound, byte[] bytes) { if (OperatingSystem.IsWindows()) diff --git a/src/LageBuch.Documents/Sections/AtemschutzSection.cs b/src/LageBuch.Documents/Sections/AtemschutzSection.cs index 9875e90..4f3579d 100644 --- a/src/LageBuch.Documents/Sections/AtemschutzSection.cs +++ b/src/LageBuch.Documents/Sections/AtemschutzSection.cs @@ -7,6 +7,9 @@ namespace LageBuch.Documents.Sections; public static class AtemschutzSection { + private static readonly string[] HeaderTitles = + ["Trupp", "Mannschaft", "Funkrufname", "Start", "Rückzug", "Ende", "Druck Start", "Druck akt."]; + public static void Compose(IContainer container, Incident incident) { container.Column(column => @@ -36,8 +39,7 @@ public static void Compose(IContainer container, Incident incident) table.Header(header => { - foreach (var title in new[] - { "Trupp", "Mannschaft", "Funkrufname", "Start", "Rückzug", "Ende", "Druck Start", "Druck akt." }) + foreach (var title in HeaderTitles) header.Cell().Element(Cells.Header).Text(title).SemiBold(); }); diff --git a/src/LageBuch.Documents/Sections/EtbSection.cs b/src/LageBuch.Documents/Sections/EtbSection.cs index 327ddc9..b04bd4c 100644 --- a/src/LageBuch.Documents/Sections/EtbSection.cs +++ b/src/LageBuch.Documents/Sections/EtbSection.cs @@ -7,6 +7,7 @@ namespace LageBuch.Documents.Sections; public static class EtbSection { + private static readonly string[] HeaderTitles = ["Zeit", "Richtung", "Von", "An", "Eintrag", "Erfasst von"]; public static void Compose(IContainer container, Incident incident) { container.Column(column => @@ -34,7 +35,7 @@ public static void Compose(IContainer container, Incident incident) table.Header(header => { - foreach (var title in new[] { "Zeit", "Richtung", "Von", "An", "Eintrag", "Erfasst von" }) + foreach (var title in HeaderTitles) header.Cell().Element(HeaderCell).Text(title).SemiBold(); }); diff --git a/src/LageBuch.Documents/Sections/FilesSection.cs b/src/LageBuch.Documents/Sections/FilesSection.cs index 7bc8832..65ac52a 100644 --- a/src/LageBuch.Documents/Sections/FilesSection.cs +++ b/src/LageBuch.Documents/Sections/FilesSection.cs @@ -13,6 +13,7 @@ namespace LageBuch.Documents.Sections; /// public static class FilesSection { + private static readonly string[] HeaderTitles = ["Name", "Hinzugefügt von", "Datum"]; public static void Compose(IContainer container, IReadOnlyList files, IReadOnlyDictionary imageBytesById) { container.Column(column => @@ -37,7 +38,7 @@ public static void Compose(IContainer container, IReadOnlyList fil table.Header(header => { - foreach (var title in new[] { "Name", "Hinzugefügt von", "Datum" }) + foreach (var title in HeaderTitles) header.Cell().Element(Cells.Header).Text(title).SemiBold(); }); diff --git a/src/LageBuch.Documents/Sections/ForcesSection.cs b/src/LageBuch.Documents/Sections/ForcesSection.cs index 00b10a9..321559b 100644 --- a/src/LageBuch.Documents/Sections/ForcesSection.cs +++ b/src/LageBuch.Documents/Sections/ForcesSection.cs @@ -8,6 +8,7 @@ namespace LageBuch.Documents.Sections; public static class ForcesSection { + private static readonly string[] HeaderTitles = ["Feuerwehr", "Funkrufname", "Stärke", "AGT", "Status", "Bemerkung"]; public static void Compose(IContainer container, Incident incident) { container.Column(column => @@ -31,7 +32,7 @@ public static void Compose(IContainer container, Incident incident) table.Header(header => { - foreach (var title in new[] { "Feuerwehr", "Funkrufname", "Stärke", "AGT", "Status", "Bemerkung" }) + foreach (var title in HeaderTitles) header.Cell().Element(Cells.Header).Text(title).SemiBold(); }); diff --git a/src/LageBuch.Documents/Sections/RolesSection.cs b/src/LageBuch.Documents/Sections/RolesSection.cs index 66995bc..07bf712 100644 --- a/src/LageBuch.Documents/Sections/RolesSection.cs +++ b/src/LageBuch.Documents/Sections/RolesSection.cs @@ -7,6 +7,7 @@ namespace LageBuch.Documents.Sections; public static class RolesSection { + private static readonly string[] HeaderTitles = ["Funktion", "Name", "Abschnitt", "Funkrufname", "Handynummer", "Von", "Bis"]; public static void Compose(IContainer container, Incident incident) { container.Column(column => @@ -37,7 +38,7 @@ public static void Compose(IContainer container, Incident incident) table.Header(header => { - foreach (var title in new[] { "Funktion", "Name", "Abschnitt", "Funkrufname", "Handynummer", "Von", "Bis" }) + foreach (var title in HeaderTitles) header.Cell().Element(Cells.Header).Text(title).SemiBold(); }); diff --git a/src/LageBuch.Documents/Sections/TasksSection.cs b/src/LageBuch.Documents/Sections/TasksSection.cs index ddb25e0..6f62d7a 100644 --- a/src/LageBuch.Documents/Sections/TasksSection.cs +++ b/src/LageBuch.Documents/Sections/TasksSection.cs @@ -7,6 +7,7 @@ namespace LageBuch.Documents.Sections; public static class TasksSection { + private static readonly string[] HeaderTitles = ["", "Wichtig", "Dringlich", "Fällig", "Zugeteilt", "Aufgabe", "Erledigt"]; public static void Compose(IContainer container, Incident incident) { container.Column(column => @@ -41,7 +42,7 @@ public static void Compose(IContainer container, Incident incident) table.Header(header => { - foreach (var title in new[] { "", "Wichtig", "Dringlich", "Fällig", "Zugeteilt", "Aufgabe", "Erledigt" }) + foreach (var title in HeaderTitles) header.Cell().Element(HeaderCell).Text(title).SemiBold(); }); diff --git a/tests/LageBuch.Acceptance.Tests/WorkspaceAcceptanceTests.cs b/tests/LageBuch.Acceptance.Tests/WorkspaceAcceptanceTests.cs index 654bda6..8570a83 100644 --- a/tests/LageBuch.Acceptance.Tests/WorkspaceAcceptanceTests.cs +++ b/tests/LageBuch.Acceptance.Tests/WorkspaceAcceptanceTests.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; @@ -68,7 +69,9 @@ private sealed class Sub : IDisposable { public void Dispose() { } } } internal sealed class NoopAlarmService : IAlarmService { + [SuppressMessage("Performance", "CA1822", Justification = "Implements IAlarmService; interface members cannot be static.")] public void Start() { } + [SuppressMessage("Performance", "CA1822", Justification = "Implements IAlarmService; interface members cannot be static.")] public void Stop() { } public void Play(AlarmSound sound) { } } diff --git a/tests/LageBuch.Sync.Hosting.Tests/TestDoubles.cs b/tests/LageBuch.Sync.Hosting.Tests/TestDoubles.cs index 050329b..6025e77 100644 --- a/tests/LageBuch.Sync.Hosting.Tests/TestDoubles.cs +++ b/tests/LageBuch.Sync.Hosting.Tests/TestDoubles.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.Sockets; using LageBuch.AppLogic; @@ -34,7 +35,9 @@ private sealed class Sub : IDisposable { public void Dispose() { } } internal sealed class NoAlarm : IAlarmService { + [SuppressMessage("Performance", "CA1822", Justification = "Implements IAlarmService; interface members cannot be static.")] public void Start() { } + [SuppressMessage("Performance", "CA1822", Justification = "Implements IAlarmService; interface members cannot be static.")] public void Stop() { } public void Play(AlarmSound sound) { } }