From 929fa20ee0af177c9ab6e4cdcce1f46e41488169 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 6 Aug 2026 21:06:24 +0200 Subject: [PATCH] Terminal nach Avalonia + konfigurierbare Zeitzone (P2-Kern) Alle vier Core-Fenster sind damit portiert. TERMINAL: - Live-Ausgabe als virtualisiertes ItemsControl ueber eine begrenzte Zeilenliste statt RichTextBox. Damit entfaellt das Auto-Clear der WinForms-Fassung, das bei Erreichen der Zeichengrenze den GESAMTEN Verlauf verwarf - jetzt werden nur die aeltesten Zeilen verdraengt (Ringpuffer, 5000 Zeilen), der juengste Verlauf bleibt immer sichtbar. Die Zeilenzahl steht in der Statuszeile. - Log-Viewer unveraendert im Funktionsumfang: JSONL-Tagesdateien, Filter nach Datum, Level, CID und Volltext, Doppelklick uebernimmt die CID (Signal-Kette verfolgen). ZEITZONE (Befund aus der Linux-Analyse, hier faellig geworden): Die Terminal-Ansicht rechnete hart gegen die WINDOWS-ID 'W. Europe Standard Time'. Auf Linux traegt die nur ueber die ICU-Zuordnung und faellt ganz aus, wenn ICU fehlt oder InvariantGlobalization gesetzt ist - das Fenster haette beim Oeffnen geworfen. Neu: PolyTraderSharp.Services.AppTimeZone + ServerSettings.ApplicationTimeZoneId (Default 'Europe/Berlin', IANA-Schreibweise). Aufloesung versucht die ID direkt, dann die jeweils andere Schreibweise (IANA<->Windows), zuletzt die Systemzeitzone - ein unbekannter Wert ist damit nie fatal, sondern erzeugt nur eine Warnung. Beide Programm-Einstiege setzen sie einmalig beim Start; laut Vorgabe wird sie bei der Installation festgelegt und nicht im laufenden Betrieb gewechselt (Aenderung verschiebt Logdatei-Tagesgrenzen). 8 neue Tests (AppTimeZoneTests) halten fest: IANA- UND Windows-ID liefern denselben UTC-Versatz (Winter +1, Sommer +2), unbekannte IDs fallen mit Warnung auf die Systemzeitzone zurueck, leere Angabe = Systemzeitzone, UTC wird korrekt umgerechnet. Verifiziert: Solution baut, 450 Tests gruen, --smoke-ui gruen (6 Fenster + Editor-Pruefung, Zeitzone loest als Europe/Berlin auf), App laeuft real, Linux-Publish laeuft. Co-Authored-By: Claude Opus 5 --- Program.cs | 5 + src/PolyTrader.App.Avalonia/Program.cs | 5 + .../Shell/CoreViews.cs | 10 +- .../ViewModels/LogRows.cs | 23 ++ .../Views/TerminalWindow.axaml | 91 ++++++++ .../Views/TerminalWindow.axaml.cs | 219 ++++++++++++++++++ src/PolyTrader.Core/Models/ServerSettings.cs | 8 + src/PolyTrader.Core/Services/AppTimeZone.cs | 85 +++++++ tests/PolyTrader.Tests/AppTimeZoneTests.cs | 70 ++++++ 9 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 src/PolyTrader.App.Avalonia/ViewModels/LogRows.cs create mode 100644 src/PolyTrader.App.Avalonia/Views/TerminalWindow.axaml create mode 100644 src/PolyTrader.App.Avalonia/Views/TerminalWindow.axaml.cs create mode 100644 src/PolyTrader.Core/Services/AppTimeZone.cs create mode 100644 tests/PolyTrader.Tests/AppTimeZoneTests.cs diff --git a/Program.cs b/Program.cs index 9677108..6e0c3e8 100644 --- a/Program.cs +++ b/Program.cs @@ -77,6 +77,11 @@ internal static class Program // Account-Credentials als auch für den gespeicherten Lizenzschlüssel gebraucht. ConfigureSecretProtection(bootLog); + // Anzeige-Zeitzone einmalig setzen (Logs, Auswertungen). Ein unbekannter Wert ist nicht + // fatal - es wird auf die Systemzeitzone ausgewichen und gewarnt. + AppTimeZone.Configure(serverSettings.ApplicationTimeZoneId, m => bootLog.Warning(m)); + bootLog.Info($"Anzeige-Zeitzone: {AppTimeZone.CurrentId}"); + // Alle bekannten Module; „modules" enthält nur die aktiven (nicht in DisabledModules). var allModules = new System.Collections.Generic.List { diff --git a/src/PolyTrader.App.Avalonia/Program.cs b/src/PolyTrader.App.Avalonia/Program.cs index 9855250..e8da7b8 100644 --- a/src/PolyTrader.App.Avalonia/Program.cs +++ b/src/PolyTrader.App.Avalonia/Program.cs @@ -93,6 +93,11 @@ namespace PolyTrader.App.Avalonia ConfigureSecretProtection(logger); + // Anzeige-Zeitzone einmalig setzen (Logs, Auswertungen). Ein unbekannter Wert ist nicht + // fatal - es wird auf die Systemzeitzone ausgewichen und gewarnt. + AppTimeZone.Configure(serverSettings.ApplicationTimeZoneId, m => logger.Warning(m)); + logger.Info($"Anzeige-Zeitzone: {AppTimeZone.CurrentId}"); + var allModules = new List { new CopyTradingModule(), diff --git a/src/PolyTrader.App.Avalonia/Shell/CoreViews.cs b/src/PolyTrader.App.Avalonia/Shell/CoreViews.cs index ffd49bc..76d9488 100644 --- a/src/PolyTrader.App.Avalonia/Shell/CoreViews.cs +++ b/src/PolyTrader.App.Avalonia/Shell/CoreViews.cs @@ -59,8 +59,14 @@ namespace PolyTrader.App.Avalonia.Shell CreateView = () => new Views.JobsWindow(host, services.GetRequiredService()) }); - // TODO Portierung: core.terminal (Order 40) folgt. - // Aufbau siehe docs/UI-SPEZIFIKATION-WinForms.md, Originalcode im Git-Tag winforms-final. + host.RegisterView(new ModuleView + { + Id = "core.terminal", + Title = "Terminal / Logs", + Group = "Core", + Order = 40, + CreateView = () => new Views.TerminalWindow(host, services.GetRequiredService()) + }); } /// diff --git a/src/PolyTrader.App.Avalonia/ViewModels/LogRows.cs b/src/PolyTrader.App.Avalonia/ViewModels/LogRows.cs new file mode 100644 index 0000000..9d36cee --- /dev/null +++ b/src/PolyTrader.App.Avalonia/ViewModels/LogRows.cs @@ -0,0 +1,23 @@ +using Avalonia.Media; + +namespace PolyTrader.App.Avalonia.ViewModels +{ + /// + /// Eine Zeile der Live-Ausgabe. Farbe wird beim Erzeugen festgelegt – die Zeile ist danach + /// unveränderlich, was die Virtualisierung billig macht (kein Change-Tracking je Zeile). + /// + public sealed class LogLine + { + public string Text { get; init; } = string.Empty; + public IBrush Brush { get; init; } = Brushes.White; + } + + /// Anzeige-Zeile des Log Viewers (JSONL-Tagesdatei). + public sealed class LogViewerRow + { + public string Time { get; init; } = string.Empty; + public string Level { get; init; } = string.Empty; + public string Cid { get; init; } = string.Empty; + public string Message { get; init; } = string.Empty; + } +} diff --git a/src/PolyTrader.App.Avalonia/Views/TerminalWindow.axaml b/src/PolyTrader.App.Avalonia/Views/TerminalWindow.axaml new file mode 100644 index 0000000..243c6c0 --- /dev/null +++ b/src/PolyTrader.App.Avalonia/Views/TerminalWindow.axaml @@ -0,0 +1,91 @@ + + + + + + + + + + + + +