| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 | using InABox.Clients;using InABox.Core;using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.Diagnostics.CodeAnalysis;using System.Linq;using System.Runtime.CompilerServices;using System.Windows;using System.Windows.Controls;using System.IO;using System.Windows.Media;using System.Windows.Media.Imaging;using InABox.WPF;namespace InABox.Wpf;public enum MessageWindowButtonPosition{    Left,    Right}public enum MessageWindowResult{    None,    OK,    Cancel,    Yes,    No,    Other}public class MessageWindowButtonDelegateArgs : EventArgs{    public MessageWindowButton Button { get; private set; }    public bool Close { get; set; } = false;    public MessageWindowButtonDelegateArgs(MessageWindowButton button, bool close)    {        Button = button;        Close = close;    }    }public delegate void MessageWindowButtonDelegate(MessageWindow window, MessageWindowButtonDelegateArgs args);public class MessageWindowButton : INotifyPropertyChanged{    public MessageWindowButtonPosition Position { get; set; }    private string _content;    public string Content    {        get => _content;        [MemberNotNull(nameof(_content))]        set        {            _content = value;            OnPropertyChanged();        }    }    public MessageWindowButtonDelegate Action { get; set; }    public MessageWindowButton(string content, MessageWindowButtonDelegate action, MessageWindowButtonPosition position)    {        Content = content;        Action = action;        Position = position;    }    public event PropertyChangedEventHandler? PropertyChanged;    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")    {        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));    }}/// <summary>/// Interaction logic for MessageWindow.xaml/// </summary>public partial class MessageWindow : Window, INotifyPropertyChanged{    public ObservableCollection<MessageWindowButton> Buttons { get; private set; } = new();    public IEnumerable<MessageWindowButton> LeftButtons => Buttons.Where(x => x.Position == MessageWindowButtonPosition.Left);    public IEnumerable<MessageWindowButton> RightButtons => Buttons.Where(x => x.Position == MessageWindowButtonPosition.Right);    private string _message = "";    public string Message    {        get => _message;        set        {            _message = value;            OnPropertyChanged();        }    }    public ImageSource? _image = null;    public ImageSource? Image    {        get => _image;        set        {            _image = value;            OnPropertyChanged();        }    }    private string _details = "";    public string Details    {        get => _details;        set        {            _details = value;            OnPropertyChanged();        }    }    public static readonly DependencyProperty ShowDetailsProperty = DependencyProperty.Register(nameof(ShowDetails), typeof(bool), typeof(MessageWindow));    public bool ShowDetails    {        get => (bool)GetValue(ShowDetailsProperty);        set => SetValue(ShowDetailsProperty, value);    }    public MessageWindowResult Result { get; set; } = MessageWindowResult.None;    public object? OtherResult { get; set; }    public MessageWindow()    {        InitializeComponent();        Buttons.CollectionChanged += Buttons_CollectionChanged;    }    private void Button_Click(object sender, RoutedEventArgs e)    {        if (sender is not Button button || button.Tag is not MessageWindowButton winButton) return;        var args = new MessageWindowButtonDelegateArgs(winButton, false);        winButton.Action(this, args);        if (args.Close)            Close();    }    private void Buttons_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)    {        OnPropertyChanged(nameof(LeftButtons));        OnPropertyChanged(nameof(RightButtons));    }    public MessageWindow AddButton(MessageWindowButton button)    {        Buttons.Add(button);        return this;    }    public MessageWindow AddOKButton(string content = "OK")    {        Buttons.Add(new MessageWindowButton(content, OKButton_Click, MessageWindowButtonPosition.Right));        return this;    }    public MessageWindow AddCancelButton(string content = "Cancel")    {        Buttons.Add(new MessageWindowButton(content, CancelButton_Click, MessageWindowButtonPosition.Right));        return this;    }    public MessageWindow AddYesButton(string content = "Yes")    {        Buttons.Add(new MessageWindowButton(content, YesButton_Click, MessageWindowButtonPosition.Right));        return this;    }    public MessageWindow AddNoButton(string content = "No")    {        Buttons.Add(new MessageWindowButton(content, NoButton_Click, MessageWindowButtonPosition.Right));        return this;    }    private void YesButton_Click(MessageWindow window, MessageWindowButtonDelegateArgs args)    {        Result = MessageWindowResult.Yes;        Close();    }    private void NoButton_Click(MessageWindow window, MessageWindowButtonDelegateArgs args)    {        Result = MessageWindowResult.No;        Close();    }    private void CancelButton_Click(MessageWindow window, MessageWindowButtonDelegateArgs args)    {        Result = MessageWindowResult.Cancel;        Close();    }    private void OKButton_Click(MessageWindow window, MessageWindowButtonDelegateArgs args)    {        Result = MessageWindowResult.OK;        Close();    }    public event PropertyChangedEventHandler? PropertyChanged;    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")    {        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));    }    #region Static Constructors    private static readonly BitmapImage _warning = InABox.Wpf.Resources.warning.AsBitmapImage();    public static BitmapImage WarningImage => _warning;    private static readonly BitmapImage _question = InABox.Wpf.Resources.help.AsBitmapImage();    public static BitmapImage QuestionImage => _question;    public static MessageWindow New()    {        return new MessageWindow();    }    public static MessageWindow NewMessage(string message, string title, ImageSource? image = null)    {        return new MessageWindow()            .Title(title)            .Message(message)            .Image(image)            .AddOKButton();    }    public static void ShowMessage(string message, string title, ImageSource? image = null)    {        NewMessage(message, title, image).Display();    }    public static MessageWindow NewWarn(string message, string title = "Warning", ImageSource? image = null)    {        return NewMessage(message, title, image);    }    public static void Warn(string message, string title = "Warning", ImageSource? image = null)    {        NewMessage(message, title, image).Display();    }    public static MessageWindow NewOKCancel(string message, string title, ImageSource? image = null)    {        return new MessageWindow()            .Title(title)            .Message(message)            .Image(image)            .AddOKButton()            .AddCancelButton();    }    public static bool ShowOKCancel(string message, string title, ImageSource? image = null)    {        return NewOKCancel(message, title, image)            .Display()            .Result == MessageWindowResult.OK;    }    public static MessageWindow NewYesNo(string message, string title, ImageSource? image = null)    {        return new MessageWindow()            .Title(title)            .Message(message)            .Image(image)            .AddYesButton()            .AddNoButton();    }    public static bool ShowYesNo(string message, string title, ImageSource? image = null)    {        return NewYesNo(message, title, image)            .Display()            .Result == MessageWindowResult.Yes;    }    public static MessageWindow NewYesNoCancel(string message, string title, ImageSource? image = null)    {        return new MessageWindow()            .Title(title)            .Message(message)            .Image(image)            .AddYesButton()            .AddNoButton()            .AddCancelButton();    }    public static MessageWindowResult ShowYesNoCancel(string message, string title, ImageSource? image = null)    {        return NewYesNoCancel(message, title, image)            .Display().Result;    }    /// <summary>    /// Display a message box for an exception, giving options to view the logs.    /// </summary>    /// <param name="message">The message to display. Set to <see langword="null"/> to default to the exception message.</param>    /// <param name="exception"></param>    /// <param name="title"></param>    /// <param name="shouldLog">If <see langword="true"/>, also logs the exception.</param>    public static MessageWindow NewError(string? message, Exception exception, string title = "Error", bool shouldLog = true, ImageSource? image = null)    {        if (shouldLog)        {            CoreUtils.LogException(ClientFactory.UserID, exception);        }        var window = new MessageWindow()            .Message(message ?? exception.Message)            .Title(title)            .Details(CoreUtils.FormatException(exception))            .Image(image ?? _warning)            .AddButton(new MessageWindowButton("Email Logs", (window, args) =>            {                EmailLogs_Click(exception);            }, MessageWindowButtonPosition.Left));        var showDetailsButton = new MessageWindowButton("Show Details", (win, args) =>        {            win.ShowDetails = !win.ShowDetails;            args.Button.Content = win.ShowDetails                ? "Hide Details"                : "Show Details";        }, MessageWindowButtonPosition.Left);        return window.AddButton(showDetailsButton)            .AddOKButton();    }    private static void EmailLogs_Click(Exception e)    {        var logFile = Path.Combine(CoreUtils.GetPath(), $"{DateTime.Today:yyyy-MM-dd}.log");        const int nRead = 1024 * 1024;        byte[] data;        using (var stream = File.OpenRead(logFile))        {            if (stream.Length > nRead)            {                stream.Seek(-nRead, SeekOrigin.End);            }            data = new BinaryReader(stream).ReadBytes(Math.Min(nRead, (int)stream.Length));        }        var message = EmailUtils.CreateMessage(            subject: "Error logs",            to: "support@prsdigital.com.au",            body: $"Error logs for PRS:\n\nException: {CoreUtils.FormatException(e)}");        message.AddAttachment("Error Logs.txt", data);        EmailUtils.OpenEmail(message);    }    /// <summary>    /// Display a message box for a non-exception error, giving options to view the logs.    /// </summary>    /// <param name="message">The message to display. Set to <see langword="null"/> to default to the exception message.</param>    /// <param name="details"></param>    /// <param name="title"></param>    /// <param name="shouldLog">If <see langword="true"/>, also logs the exception.</param>    public static MessageWindow NewError(string message, string? details = null, string title = "Error", bool shouldLog = true, ImageSource? image = null)    {        if (shouldLog)        {            Logger.Send(LogType.Error, ClientFactory.UserID, details ?? message);        }        var window = new MessageWindow()            .Message(message)            .Title(title);        if(details is not null)        {            window.Details(details);        }        window.Image(image ?? _warning)            .AddButton(new MessageWindowButton(                "Email Logs",                (window, button) => EmailLogs_Click(new Exception(details ?? message)),                MessageWindowButtonPosition.Left));        if(details is not null)        {            var showDetailsButton = new MessageWindowButton("Show Details", (win, args) =>            {                win.ShowDetails = !win.ShowDetails;                args.Button.Content = win.ShowDetails                    ? "Hide Details"                    : "Show Details";            }, MessageWindowButtonPosition.Left);            window.AddButton(showDetailsButton);        }        return window.AddOKButton();    }    public static void ShowError(string? message, Exception exception, string title = "Error", bool shouldLog = true, ImageSource? image = null)    {        NewError(message, exception, title, shouldLog, image).Display();    }    public static void ShowError(string message, string details, string title = "Error", bool shouldLog = true, ImageSource? image = null)    {        NewError(message, details, title, shouldLog, image).Display();    }    private static void ShowLogs_Click(MessageWindow window, MessageWindowButton button)    {        var console = new MessageWindowConsole("Logs", Path.Combine(CoreUtils.GetPath(), string.Format("{0:yyyy-MM-dd}.log", DateTime.Today)));        console.ShowDialog();    }    #endregion}public static class MessageWindowBuilder{    public static MessageWindow Title(this MessageWindow window, string title)    {        window.Title = title;        return window;    }    public static MessageWindow Message(this MessageWindow window, string message)    {        window.Message = message;        return window;    }    public static MessageWindow Image(this MessageWindow window, ImageSource? image)    {        window.Image = image;        return window;    }    public static MessageWindow Icon(this MessageWindow window, ImageSource image)    {        window.Icon = image;        return window;    }    public static MessageWindow Details(this MessageWindow window, string details)    {        window.Details = details;        return window;    }    public static MessageWindow Display(this MessageWindow window)    {        window.ShowDialog();        return window;    }}public class MessageWindowConsole : Console.Console{    public string FileName { get; set; }    public MessageWindowConsole(string description, string file) : base(description)    {        FileName = file;        ConsoleControl.AllowLoadLogButton = false;    }    protected override void OnLoaded()    {        base.OnLoaded();        if (File.Exists(FileName))        {            var lines = File.ReadLines(FileName);            ConsoleControl.LoadLogEntries(lines);        }    }    protected override string GetLogDirectory()    {        return CoreUtils.GetPath();    }}
 |