diff --git a/CHANGELOG.md b/CHANGELOG.md index 078e093b..b3e5eba0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,11 @@ Versionsschema ist `x.x.x.x` (siehe `release.sh`). ### Hinzugefuegt +- **Protokoll automatisch leeren (Einstellung).** Neuer Wert "Protokoll + auto-leeren - Eintraege aelter als (Tage)". Bei 0 (Standard) bleibt alles + erhalten; bei >0 werden aeltere Eintraege automatisch entfernt (beim Start, + vor jedem Sync, beim Oeffnen des Protokolls und beim Speichern der + Einstellungen). - **Protokoll zeigt jetzt, WAS geaendert wurde.** Pro Sync werden die einzelnen Aktionen (erstellt / aktualisiert / geloescht / verknuepft / zusammengefuehrt je Kontakt) ins Protokoll geschrieben - sowohl beim manuellen Sync (Fenster) als diff --git a/src/StarfaceOutlookSync/Models/UserSettings.cs b/src/StarfaceOutlookSync/Models/UserSettings.cs index 5877679a..a75b9ac0 100644 --- a/src/StarfaceOutlookSync/Models/UserSettings.cs +++ b/src/StarfaceOutlookSync/Models/UserSettings.cs @@ -16,6 +16,10 @@ namespace StarfaceOutlookSync.Models public bool NotificationsEnabled { get; set; } = true; public bool NotifyWarningsErrors { get; set; } = true; + // Protokoll-Eintraege aelter als X Tage automatisch entfernen. 0 = aus + // (alle Eintraege bleiben erhalten). + public int LogRetentionDays { get; set; } = 0; + // Gemeinsames Verzeichnis (Netzlaufwerk/UNC) fuer die clientuebergreifende // Sync-Sperre. Leer = keine Sperre (nur lokaler Schutz). Verhindert, dass // mehrere Arbeitsplaetze gleichzeitig dasselbe Adressbuch synchronisieren. diff --git a/src/StarfaceOutlookSync/Services/Logger.cs b/src/StarfaceOutlookSync/Services/Logger.cs index e0f3f9c4..014c4de0 100644 --- a/src/StarfaceOutlookSync/Services/Logger.cs +++ b/src/StarfaceOutlookSync/Services/Logger.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; @@ -63,6 +65,48 @@ namespace StarfaceOutlookSync.Services catch { return ""; } } + /// + /// Entfernt Protokoll-Eintraege, die aelter als + /// Tage sind. days <= 0 -> nichts tun (alle Eintraege bleiben). + /// + public static void PruneOlderThan(int days) + { + if (days <= 0) return; + try + { + lock (_lock) + { + if (!File.Exists(LogFilePath)) return; + var cutoff = DateTime.Now.AddDays(-days); + var lines = File.ReadAllLines(LogFilePath, Encoding.UTF8); + var kept = new List(lines.Length); + foreach (var line in lines) + { + // Eintraege ohne erkennbaren Zeitstempel (z.B. Fortsetzungs- + // zeilen) bleiben erhalten; nur datierte Alt-Eintraege fliegen raus. + if (TryParseLineDate(line, out var dt) && dt < cutoff) + continue; + kept.Add(line); + } + if (kept.Count != lines.Length) + File.WriteAllLines(LogFilePath, kept, Encoding.UTF8); + } + } + catch { } + } + + private static bool TryParseLineDate(string line, out DateTime dt) + { + dt = default; + // Format: "[yyyy-MM-dd HH:mm:ss] ..." + if (line != null && line.Length >= 21 && line[0] == '[' && line[20] == ']') + { + return DateTime.TryParseExact(line.Substring(1, 19), "yyyy-MM-dd HH:mm:ss", + CultureInfo.InvariantCulture, DateTimeStyles.None, out dt); + } + return false; + } + public static void Clear() { try diff --git a/src/StarfaceOutlookSync/Services/SyncCoordinator.cs b/src/StarfaceOutlookSync/Services/SyncCoordinator.cs index ac3ad821..98850f69 100644 --- a/src/StarfaceOutlookSync/Services/SyncCoordinator.cs +++ b/src/StarfaceOutlookSync/Services/SyncCoordinator.cs @@ -53,7 +53,9 @@ namespace StarfaceOutlookSync.Services } SyncLock crossLock = null; - var sharedDir = UserSettings.Load().SharedDirectory; + var settings = UserSettings.Load(); + Logger.PruneOlderThan(settings.LogRetentionDays); + var sharedDir = settings.SharedDirectory; try { crossLock = await AcquireCrossClientLock(sharedDir, status); diff --git a/src/StarfaceOutlookSync/UI/LogViewerForm.cs b/src/StarfaceOutlookSync/UI/LogViewerForm.cs index 034c3760..fd69b3f9 100644 --- a/src/StarfaceOutlookSync/UI/LogViewerForm.cs +++ b/src/StarfaceOutlookSync/UI/LogViewerForm.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Windows.Forms; +using StarfaceOutlookSync.Models; using StarfaceOutlookSync.Services; namespace StarfaceOutlookSync.UI @@ -72,6 +73,7 @@ namespace StarfaceOutlookSync.UI private void LoadLog() { + Logger.PruneOlderThan(UserSettings.Load().LogRetentionDays); _txt.Text = Logger.ReadAll(); _txt.SelectionStart = _txt.TextLength; _txt.ScrollToCaret(); diff --git a/src/StarfaceOutlookSync/UI/MainForm.cs b/src/StarfaceOutlookSync/UI/MainForm.cs index fc79387d..570ad1bf 100644 --- a/src/StarfaceOutlookSync/UI/MainForm.cs +++ b/src/StarfaceOutlookSync/UI/MainForm.cs @@ -39,6 +39,9 @@ namespace StarfaceOutlookSync.UI var settings = UserSettings.Load(); settings.ApplyOutlookSecuritySetting(); + // Protokoll bei Bedarf auf das eingestellte Alter eindampfen. + Logger.PruneOlderThan(settings.LogRetentionDays); + if (settings.StartMinimized) { WindowState = FormWindowState.Minimized; diff --git a/src/StarfaceOutlookSync/UI/SettingsForm.cs b/src/StarfaceOutlookSync/UI/SettingsForm.cs index 6c25d408..ca1afd0f 100644 --- a/src/StarfaceOutlookSync/UI/SettingsForm.cs +++ b/src/StarfaceOutlookSync/UI/SettingsForm.cs @@ -1,6 +1,7 @@ using System.Drawing; using System.Windows.Forms; using StarfaceOutlookSync.Models; +using StarfaceOutlookSync.Services; namespace StarfaceOutlookSync.UI { @@ -8,6 +9,7 @@ namespace StarfaceOutlookSync.UI { private CheckBox _chkStartMinimized, _chkSyncOnStart, _chkAutoAcceptOutlook; private CheckBox _chkNotifGeneral, _chkNotifWarn; + private NumericUpDown _numLogRetention; private TextBox _txtSharedDir; private Button _btnBrowseShared; private Button _btnSave, _btnCancel; @@ -76,21 +78,33 @@ namespace StarfaceOutlookSync.UI Checked = _settings.NotifyWarningsErrors }; + var lblLogRetention = new Label + { + Text = "Protokoll auto-leeren - Eintraege aelter als (Tage, 0 = aus):", + Left = 20, Top = 204, AutoSize = true + }; + + _numLogRetention = new NumericUpDown + { + Left = 305, Top = 200, Width = 55, Minimum = 0, Maximum = 3650, + Value = System.Math.Max(0, System.Math.Min(3650, _settings.LogRetentionDays)) + }; + var lblShared = new Label { Text = "Gemeinsames Verzeichnis fuer Sync-Sperre (Mehrplatz, optional):", - Left = 20, Top = 206, AutoSize = true + Left = 20, Top = 240, AutoSize = true }; _txtSharedDir = new TextBox { - Left = 20, Top = 228, Width = 250, + Left = 20, Top = 262, Width = 250, Text = _settings.SharedDirectory }; _btnBrowseShared = new Button { - Text = "...", Left = 274, Top = 227, Width = 36, Height = 24 + Text = "...", Left = 274, Top = 261, Width = 36, Height = 24 }; _btnBrowseShared.Click += (s, e) => BrowseSharedDir(); @@ -98,26 +112,26 @@ namespace StarfaceOutlookSync.UI { Text = "Netzlaufwerk/UNC, das alle Arbeitsplaetze erreichen. Leer = keine\n" + "clientuebergreifende Sperre (nur Schutz auf diesem PC).", - Left = 20, Top = 254, Width = 330, Height = 32, + Left = 20, Top = 288, Width = 330, Height = 32, ForeColor = Color.Gray, Font = new Font("Segoe UI", 8) }; _btnSave = new Button { - Text = "Speichern", Left = 95, Top = 300, Width = 85, Height = 28, + Text = "Speichern", Left = 95, Top = 334, Width = 85, Height = 28, DialogResult = DialogResult.None }; _btnSave.Click += (s, e) => Save(); _btnCancel = new Button { - Text = "Abbrechen", Left = 189, Top = 300, Width = 85, Height = 28, + Text = "Abbrechen", Left = 189, Top = 334, Width = 85, Height = 28, DialogResult = DialogResult.Cancel }; - Size = new Size(380, 390); + Size = new Size(380, 424); Controls.AddRange(new Control[] { _chkStartMinimized, _chkSyncOnStart, _chkAutoAcceptOutlook, lblHint, - _chkNotifGeneral, _chkNotifWarn, + _chkNotifGeneral, _chkNotifWarn, lblLogRetention, _numLogRetention, lblShared, _txtSharedDir, _btnBrowseShared, lblSharedHint, _btnSave, _btnCancel }); AcceptButton = _btnSave; CancelButton = _btnCancel; @@ -144,8 +158,13 @@ namespace StarfaceOutlookSync.UI _settings.AutoAcceptOutlookPrompt = _chkAutoAcceptOutlook.Checked; _settings.NotificationsEnabled = _chkNotifGeneral.Checked; _settings.NotifyWarningsErrors = _chkNotifWarn.Checked; + _settings.LogRetentionDays = (int)_numLogRetention.Value; _settings.SharedDirectory = _txtSharedDir.Text.Trim(); _settings.Save(); + + // Sofort anwenden, damit der Effekt direkt sichtbar ist. + Logger.PruneOlderThan(_settings.LogRetentionDays); + DialogResult = DialogResult.OK; Close(); }