diff --git a/src/LageBuch.App/Services/SystemAlarmService.cs b/src/LageBuch.App/Services/SystemAlarmService.cs index 4f08074..f316b09 100644 --- a/src/LageBuch.App/Services/SystemAlarmService.cs +++ b/src/LageBuch.App/Services/SystemAlarmService.cs @@ -120,6 +120,7 @@ private void PlayBlocking(AlarmSound sound, byte[] bytes) } } + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [DllImport("winmm.dll", CharSet = CharSet.Auto)] private static extern bool PlaySound(byte[]? data, IntPtr hModule, uint flags); } diff --git a/src/LageBuch.AppLogic/Services/IncidentStore.cs b/src/LageBuch.AppLogic/Services/IncidentStore.cs index 270baf5..470acb8 100644 --- a/src/LageBuch.AppLogic/Services/IncidentStore.cs +++ b/src/LageBuch.AppLogic/Services/IncidentStore.cs @@ -5,7 +5,7 @@ namespace LageBuch.AppLogic.Services; public sealed class IncidentStore : IIncidentStore { - private readonly IIncidentFileStore _fileStore = new IncidentFileStore(); +private readonly IncidentFileStore _fileStore = new IncidentFileStore(); public void Save(string path, Incident incident) => IncidentRepository.Save(path, incident); diff --git a/src/LageBuch.AppLogic/ViewModels/FilesViewModel.cs b/src/LageBuch.AppLogic/ViewModels/FilesViewModel.cs index 2590df1..fcc9249 100644 --- a/src/LageBuch.AppLogic/ViewModels/FilesViewModel.cs +++ b/src/LageBuch.AppLogic/ViewModels/FilesViewModel.cs @@ -154,13 +154,13 @@ private async Task OpenFileAsync(IncidentFileRow row) // Mirrors IncidentFile.AllowedContentTypes' extensions — the picker already restricts choice to // these, this just maps the chosen local path back to the MIME type the domain expects. - private static string ContentTypeFor(string path) => Path.GetExtension(path).ToLowerInvariant() switch + private static string ContentTypeFor(string path) => Path.GetExtension(path).ToUpperInvariant() switch { - ".jpg" or ".jpeg" => "image/jpeg", - ".png" => "image/png", - ".gif" => "image/gif", - ".webp" => "image/webp", - ".pdf" => "application/pdf", + ".JPG" or ".JPEG" => "image/jpeg", + ".PNG" => "image/png", + ".GIF" => "image/gif", + ".WEBP" => "image/webp", + ".PDF" => "application/pdf", _ => "application/octet-stream" }; } diff --git a/src/LageBuch.AppLogic/ViewModels/MainWindowViewModel.cs b/src/LageBuch.AppLogic/ViewModels/MainWindowViewModel.cs index 7759419..2e95471 100644 --- a/src/LageBuch.AppLogic/ViewModels/MainWindowViewModel.cs +++ b/src/LageBuch.AppLogic/ViewModels/MainWindowViewModel.cs @@ -29,9 +29,9 @@ public MainWindowViewModel(HomeViewModel home, MasterDataEditorViewModel editor, // away (IncidentWorkspaceViewModel.GoHomeRequested). LeaveAsync is a no-op for a local session. private void ShowWorkspace(IncidentWorkspaceViewModel ws) { - ws.GoHomeRequested = () => + ws.GoHomeRequested = async () => { - _ = ws.LeaveAsync(); + await ws.LeaveAsync(); CurrentView = _home; }; CurrentView = ws; diff --git a/src/LageBuch.Domain/Atemschutz/AtemschutzTrupp.cs b/src/LageBuch.Domain/Atemschutz/AtemschutzTrupp.cs index a8f68a4..509d13f 100644 --- a/src/LageBuch.Domain/Atemschutz/AtemschutzTrupp.cs +++ b/src/LageBuch.Domain/Atemschutz/AtemschutzTrupp.cs @@ -160,7 +160,7 @@ public static bool IsLpaTrupp(string designation) => public static int RequiredMemberCount(string designation) => IsChemicalTrupp(designation) ? ChemicalMemberCount : StandardMemberCount; - private static void ValidateCrew(string designation, IReadOnlyList crew) + private static void ValidateCrew(string designation, List crew) { // Atemschutz is never a solo activity -- a Trupp is the unit that goes under air together, // and the monitoring sheet has no concept of a single wearer. Enforcing the count here diff --git a/src/LageBuch.Persistence/MasterData/MasterDataSet.cs b/src/LageBuch.Persistence/MasterData/MasterDataSet.cs index 46ecbb5..124ba2b 100644 --- a/src/LageBuch.Persistence/MasterData/MasterDataSet.cs +++ b/src/LageBuch.Persistence/MasterData/MasterDataSet.cs @@ -231,6 +231,12 @@ public sealed record MasterDataSet( /// public static class MasterDataJson { + private static readonly JsonSerializerOptions ExportOptions = new() + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + }; + public static MasterDataSet Parse(Stream json) { using var doc = JsonDocument.Parse(json); @@ -400,10 +406,6 @@ public static string Serialize(MasterDataSet set) }, }; - return JsonSerializer.Serialize(model, new JsonSerializerOptions - { - WriteIndented = true, - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, - }); + return JsonSerializer.Serialize(model, ExportOptions); } } diff --git a/src/LageBuch.Persistence/MasterData/MasterDataStore.cs b/src/LageBuch.Persistence/MasterData/MasterDataStore.cs index 2a598ea..285512e 100644 --- a/src/LageBuch.Persistence/MasterData/MasterDataStore.cs +++ b/src/LageBuch.Persistence/MasterData/MasterDataStore.cs @@ -93,7 +93,7 @@ private static void InsertChecklistTemplate( } } - private static IEnumerable<(string Key, int Value)> SettingsRows(IncidentSettings s) => new[] + private static (string Key, int Value)[] SettingsRows(IncidentSettings s) => new[] { ("ils_reminder_interval_minutes", s.IlsReminderIntervalMinutes), ("ils_reminder_follow_up_interval_minutes", s.IlsReminderFollowUpIntervalMinutes), diff --git a/src/LageBuch.Sync/SyncCommand.cs b/src/LageBuch.Sync/SyncCommand.cs index 29ba013..6774278 100644 --- a/src/LageBuch.Sync/SyncCommand.cs +++ b/src/LageBuch.Sync/SyncCommand.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using LageBuch.Domain.CoMeasurement; using LageBuch.Domain.Etb; @@ -113,6 +114,7 @@ public sealed record CloseIncidentCommand(OperatorDto Operator) : SyncCommand; // Bytes ride this one-shot upload command (System.Text.Json base64-encodes byte[] automatically), // but never the broadcast snapshot that follows every command — see IncidentSnapshot/IncidentFileDto. +[SuppressMessage("Performance", "CA1819", Justification = "byte[] is the wire representation System.Text.Json base64-encodes; a read-only wrapper would need a custom converter.")] public sealed record AddFileCommand(OperatorDto Operator, string FileName, string ContentType, byte[] Bytes) : SyncCommand; // No operator on the wire: renaming is a silent label correction (no ETB entry), unlike every