Add persistent log file and "Protokoll" viewer button

Tray-Meldungen verschwinden - daher ein dauerhaftes Protokoll.

- Logger: threadsicheres Datei-Log in %AppData%\StarfaceOutlookSync\sync.log
  mit Rotation bei 2 MB.
- MainForm protokolliert Sync-Start, Ergebnis, Konflikte (lokal + von anderen
  Arbeitsplaetzen), Fehler und uebersprungene Laeufe (Sperre).
- Neuer Button "Protokoll" oeffnet LogViewerForm (Aktualisieren/Leeren/Ordner
  oeffnen, scrollt ans Ende).
- README/CHANGELOG aktualisiert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 13:17:53 +02:00
parent b8a7fda7bf
commit 23223fe0be
5 changed files with 205 additions and 2 deletions
@@ -0,0 +1,90 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using StarfaceOutlookSync.Services;
namespace StarfaceOutlookSync.UI
{
/// <summary>Zeigt das Sync-Protokoll an (read-only) mit Aktualisieren/Leeren.</summary>
public class LogViewerForm : Form
{
private TextBox _txt;
private Button _btnClose;
private Panel _panel;
public LogViewerForm()
{
Text = "Protokoll";
Size = new Size(720, 500);
StartPosition = FormStartPosition.CenterParent;
Font = new Font("Segoe UI", 9);
_txt = new TextBox
{
Multiline = true,
ReadOnly = true,
ScrollBars = ScrollBars.Both,
WordWrap = false,
Dock = DockStyle.Fill,
BackColor = Color.White,
Font = new Font("Consolas", 9)
};
_panel = new Panel { Dock = DockStyle.Bottom, Height = 44 };
var btnRefresh = new Button { Text = "Aktualisieren", Left = 10, Top = 8, Width = 100, Height = 28 };
btnRefresh.Click += (s, e) => LoadLog();
var btnClear = new Button { Text = "Leeren", Left = 118, Top = 8, Width = 80, Height = 28 };
btnClear.Click += (s, e) =>
{
if (MessageBox.Show("Protokoll wirklich leeren?", "Protokoll",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
Logger.Clear();
LoadLog();
}
};
var btnFolder = new Button { Text = "Ordner oeffnen", Left = 206, Top = 8, Width = 120, Height = 28 };
btnFolder.Click += (s, e) => OpenFolder();
_btnClose = new Button
{
Text = "Schliessen", Top = 8, Width = 100, Height = 28,
Anchor = AnchorStyles.Top | AnchorStyles.Right
};
_btnClose.Click += (s, e) => Close();
_panel.Controls.AddRange(new Control[] { btnRefresh, btnClear, btnFolder, _btnClose });
Controls.Add(_txt);
Controls.Add(_panel);
Load += (s, e) =>
{
_btnClose.Left = _panel.ClientSize.Width - _btnClose.Width - 10;
LoadLog();
};
}
private void LoadLog()
{
_txt.Text = Logger.ReadAll();
_txt.SelectionStart = _txt.TextLength;
_txt.ScrollToCaret();
}
private void OpenFolder()
{
try
{
var dir = Path.GetDirectoryName(Logger.LogFilePath);
Process.Start(new ProcessStartInfo { FileName = dir, UseShellExecute = true });
}
catch { }
}
}
}