From 66db4e6ddd51ff6cee5aa1a9186b6210c2b9e3f6 Mon Sep 17 00:00:00 2001 From: Justin Swanson Date: Tue, 22 Oct 2019 23:15:42 -0500 Subject: [PATCH] Refactored logging to all hook into Utils.Log Log collection moved up to MainWindow. Since there will be many sub-VMs moving forward, a singleton based setup was desired. RxUI's Splat was an option, but we already had Utils.Log right there. Also now GUI printed messages will go to the log on the disk for later inspection. --- Wabbajack/View Models/AppState.cs | 25 ++++++++--------------- Wabbajack/View Models/MainWindowVM.cs | 29 +++++++++++++++++++++++++++ Wabbajack/View Models/SlideShow.cs | 5 +++-- Wabbajack/Views/MainWindow.xaml | 2 +- Wabbajack/Views/MainWindow.xaml.cs | 26 +++++++++++------------- 5 files changed, 53 insertions(+), 34 deletions(-) diff --git a/Wabbajack/View Models/AppState.cs b/Wabbajack/View Models/AppState.cs index f283655b..b29a680b 100644 --- a/Wabbajack/View Models/AppState.cs +++ b/Wabbajack/View Models/AppState.cs @@ -1,4 +1,4 @@ -using Syroot.Windows.IO; +using Syroot.Windows.IO; using System; using ReactiveUI; using System.Collections.Generic; @@ -104,8 +104,6 @@ namespace Wabbajack this.Slideshow = new SlideShow(this); } - public ObservableCollection Log { get; } = new ObservableCollection(); - private string _Location; public string Location { get => _Location; set => this.RaiseAndSetIfChanged(ref _Location, value); } @@ -115,8 +113,6 @@ namespace Wabbajack private string _DownloadLocation; public string DownloadLocation { get => _DownloadLocation; set => this.RaiseAndSetIfChanged(ref _DownloadLocation, value); } - public string LogFile { get; } - private void ExecuteChangePath() { switch (this.Mode) @@ -233,17 +229,12 @@ namespace Wabbajack return validationMessage; } - public void LogMsg(string msg) - { - Application.Current.Dispatcher.Invoke(() => Log.Add(msg)); - } - private void ConfigureForBuild() { var profile_folder = Path.GetDirectoryName(Location); var mo2folder = Path.GetDirectoryName(Path.GetDirectoryName(profile_folder)); if (!File.Exists(Path.Combine(mo2folder, "ModOrganizer.exe"))) - LogMsg($"Error! No ModOrganizer2.exe found in {mo2folder}"); + Utils.Log($"Error! No ModOrganizer2.exe found in {mo2folder}"); var profile_name = Path.GetFileName(profile_folder); this.ModListName = profile_name; @@ -296,9 +287,9 @@ namespace Wabbajack catch (Exception ex) { while (ex.InnerException != null) ex = ex.InnerException; - LogMsg(ex.StackTrace); - LogMsg(ex.ToString()); - LogMsg($"{ex.Message} - Can't continue"); + Utils.Log(ex.StackTrace); + Utils.Log(ex.ToString()); + Utils.Log($"{ex.Message} - Can't continue"); } finally { @@ -335,9 +326,9 @@ namespace Wabbajack catch (Exception ex) { while (ex.InnerException != null) ex = ex.InnerException; - LogMsg(ex.StackTrace); - LogMsg(ex.ToString()); - LogMsg($"{ex.Message} - Can't continue"); + Utils.Log(ex.StackTrace); + Utils.Log(ex.ToString()); + Utils.Log($"{ex.Message} - Can't continue"); } finally { diff --git a/Wabbajack/View Models/MainWindowVM.cs b/Wabbajack/View Models/MainWindowVM.cs index 204926e5..c1c493b1 100644 --- a/Wabbajack/View Models/MainWindowVM.cs +++ b/Wabbajack/View Models/MainWindowVM.cs @@ -3,17 +3,23 @@ using DynamicData.Binding; using ReactiveUI; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Text; using System.Threading.Tasks; +using System.Windows; using Wabbajack.Common; using Wabbajack.Lib; namespace Wabbajack { + /// + /// Main View Model for the application. + /// Keeps track of which sub view is being shown in the window, and has some singleton wiring like WorkQueue and Logging. + /// public class MainWindowVM : ViewModel { public AppState AppState { get; } @@ -28,8 +34,25 @@ namespace Wabbajack public IObservable StatusObservable => _statusSubject; public ObservableCollectionExtended StatusList { get; } = new ObservableCollectionExtended(); + private Subject _logSubj = new Subject(); + public ObservableCollectionExtended Log { get; } = new ObservableCollectionExtended(); + public MainWindowVM(RunMode mode) { + // Set up logging + _logSubj + .ToObservableChangeSet() + .Buffer(TimeSpan.FromMilliseconds(250)) + .Where(l => l.Count > 0) + .FlattenBufferResult() + .Top(5000) + .ObserveOn(RxApp.MainThreadScheduler) + .Bind(this.Log) + .Subscribe() + .DisposeWith(this.CompositeDisposable); + Utils.SetLoggerFn(s => _logSubj.OnNext(s)); + Utils.SetStatusFn((msg, progress) => WorkQueue.Report(msg, progress)); + this.AppState = new AppState(this, mode); // Initialize work queue @@ -56,5 +79,11 @@ namespace Wabbajack max = 1; QueueProgress = current * 100 / max; } + + public override void Dispose() + { + base.Dispose(); + Utils.SetLoggerFn(s => { }); + } } } diff --git a/Wabbajack/View Models/SlideShow.cs b/Wabbajack/View Models/SlideShow.cs index 49b7de46..ff9bfb13 100644 --- a/Wabbajack/View Models/SlideShow.cs +++ b/Wabbajack/View Models/SlideShow.cs @@ -1,4 +1,5 @@ using ReactiveUI; +using Splat; using System; using System.Collections.Generic; using System.Diagnostics; @@ -124,9 +125,9 @@ namespace Wabbajack return image; } } - catch (Exception) + catch (Exception ex) { - this.AppState.LogMsg("Error loading splash image."); + this.Log().Warn(ex, "Error loading splash image."); } } return this.WabbajackLogo; diff --git a/Wabbajack/Views/MainWindow.xaml b/Wabbajack/Views/MainWindow.xaml index 47c3e5c1..6d3304e9 100644 --- a/Wabbajack/Views/MainWindow.xaml +++ b/Wabbajack/Views/MainWindow.xaml @@ -73,7 +73,7 @@ Grid.Row="4" Margin="0,0,2,0" local:AutoScrollBehavior.ScrollOnNewItem="True" - ItemsSource="{Binding Log}" /> + ItemsSource="{Binding MWVM.Log}" /> diff --git a/Wabbajack/Views/MainWindow.xaml.cs b/Wabbajack/Views/MainWindow.xaml.cs index 2d616317..9314c960 100644 --- a/Wabbajack/Views/MainWindow.xaml.cs +++ b/Wabbajack/Views/MainWindow.xaml.cs @@ -15,7 +15,7 @@ namespace Wabbajack /// public partial class MainWindow : Window { - private AppState _state; + private MainWindowVM _mwvm; public MainWindow(RunMode mode, string source) { @@ -23,14 +23,11 @@ namespace Wabbajack InitializeComponent(); - var mainVM = new MainWindowVM(mode); - var context = mainVM.AppState; - context.LogMsg($"Wabbajack Build - {ThisAssembly.Git.Sha}"); - SetupHandlers(context); - DataContext = mainVM; - - Utils.SetLoggerFn(s => context.LogMsg(s)); - Utils.SetStatusFn((msg, progress) => WorkQueue.Report(msg, progress)); + this._mwvm = new MainWindowVM(mode); + var context = _mwvm.AppState; + Utils.Log($"Wabbajack Build - {ThisAssembly.Git.Sha}"); + SetupHandlers(); + DataContext = _mwvm; new Thread(() => { @@ -71,25 +68,26 @@ namespace Wabbajack }).Start(); } - private void SetupHandlers(AppState state) + private void SetupHandlers() { - _state = state; AppDomain.CurrentDomain.UnhandledException += AppHandler; } private void AppHandler(object sender, UnhandledExceptionEventArgs e) { - _state.LogMsg("Uncaught error:"); - _state.LogMsg(((Exception)e.ExceptionObject).ExceptionToString()); + Utils.Log("Uncaught error:"); + Utils.Log(((Exception)e.ExceptionObject).ExceptionToString()); } - internal bool ExitWhenClosing = true; private void Window_Closing(object sender, CancelEventArgs e) { + _mwvm.Dispose(); if (ExitWhenClosing) + { Application.Current.Shutdown(); + } } } } \ No newline at end of file