Skip to content

Commit

Permalink
Add log tracer window
Browse files Browse the repository at this point in the history
  • Loading branch information
pizzaboxer committed Jul 20, 2023
1 parent 05185e9 commit 53a6488
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 31 deletions.
9 changes: 7 additions & 2 deletions Bloxstrap/RobloxActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ public class RobloxActivity : IDisposable

private int _logEntriesRead = 0;

public event EventHandler<string>? OnLogEntry;
public event EventHandler? OnGameJoin;
public event EventHandler? OnGameLeave;
public event EventHandler<GameMessage>? OnGameMessage;

private Dictionary<string, string> GeolcationCache = new();

public string LogFilename = null!;

// these are values to use assuming the player isn't currently in a game
// keep in mind ActivityIsTeleport is only reset by DiscordRichPresence when it's done accessing it
// because of the weird chronology of where the teleporting entry is outputted, there's no way to reset it in here
Expand Down Expand Up @@ -72,8 +75,9 @@ public async void StartWatcher()
await Task.Delay(1000);
}

LogFilename = logFileInfo.Name;
FileStream logFileStream = logFileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
App.Logger.WriteLine($"[RobloxActivity::StartWatcher] Opened {logFileInfo.Name}");
App.Logger.WriteLine($"[RobloxActivity::StartWatcher] Opened {LogFilename}");

AutoResetEvent logUpdatedEvent = new(false);
FileSystemWatcher logWatcher = new()
Expand All @@ -99,7 +103,8 @@ public async void StartWatcher()

private void ExamineLogEntry(string entry)
{
// App.Logger.WriteLine(entry);
OnLogEntry?.Invoke(this, entry);

_logEntriesRead += 1;

// debug stats to ensure that the log reader is working correctly
Expand Down
38 changes: 38 additions & 0 deletions Bloxstrap/UI/Elements/ContextMenu/LogTracer.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<ui:UiWindow x:Class="Bloxstrap.UI.Elements.ContextMenu.LogTracer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Bloxstrap.UI.Elements.ContextMenu"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:models="clr-namespace:Bloxstrap.UI.ViewModels.ContextMenu"
d:DataContext="{d:DesignInstance Type=models:LogTracerViewModel}"
mc:Ignorable="d"
Title="Log tracer"
Width="800"
Height="480"
Background="{ui:ThemeResource ApplicationBackgroundBrush}"
ExtendsContentIntoTitleBar="True"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<ui:TitleBar Grid.Row="0" Grid.ColumnSpan="2" Padding="8" x:Name="RootTitleBar" Title="Log tracer" ShowMinimize="True" ShowMaximize="True" CanMaximize="True" KeyboardNavigation.TabNavigation="None" Icon="pack://application:,,,/Bloxstrap.ico" />

<TextBlock Grid.Row="1" Padding="12" Text="{Binding LogLocation, Mode=OneWay, StringFormat='Tracing \{0\}'}" />

<ScrollViewer x:Name="ScrollViewer" Grid.Row="2">
<RichTextBox Grid.Row="1" Block.LineHeight="2" IsReadOnly="True" Background="Transparent" BorderThickness="0" TextChanged="RichTextBox_TextChanged">
<FlowDocument x:Name="FlowDocument">
<Paragraph FontFamily="Courier New" FontSize="14">
<Run Text="{Binding LogContents, Mode=OneWay}" />
</Paragraph>
</FlowDocument>
</RichTextBox>
</ScrollViewer>
</Grid>
</ui:UiWindow>
24 changes: 24 additions & 0 deletions Bloxstrap/UI/Elements/ContextMenu/LogTracer.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Windows.Controls;

using Bloxstrap.UI.ViewModels.ContextMenu;

namespace Bloxstrap.UI.Elements.ContextMenu
{
/// <summary>
/// Interaction logic for LogTracer.xaml
/// </summary>
public partial class LogTracer
{
private readonly LogTracerViewModel _viewModel;

public LogTracer(RobloxActivity activityWatcher)
{
_viewModel = new LogTracerViewModel(this, activityWatcher);
DataContext = _viewModel;

InitializeComponent();
}

private void RichTextBox_TextChanged(object sender, TextChangedEventArgs e) => ScrollViewer.ScrollToEnd();
}
}
1 change: 1 addition & 0 deletions Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<Separator />
<MenuItem x:Name="RichPresenceMenuItem" Header="Discord Rich Presence" IsCheckable="True" IsChecked="True" Visibility="Collapsed" />
<MenuItem x:Name="ServerDetailsMenuItem" Header="See server details" Visibility="Collapsed" />
<MenuItem x:Name="LogTracerMenuItem" Header="Open log tracer" Visibility="Collapsed" />
</ContextMenu>
</ui:UiWindow.ContextMenu>
</ui:UiWindow>
38 changes: 18 additions & 20 deletions Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,27 @@
ExtendsContentIntoTitleBar="True"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<ui:TitleBar Grid.Row="0" Grid.ColumnSpan="2" Padding="8" x:Name="RootTitleBar" Title="Server information" ShowMinimize="False" ShowMaximize="False" CanMaximize="False" KeyboardNavigation.TabNavigation="None" Icon="pack://application:,,,/Bloxstrap.ico" />
<ui:TitleBar Grid.Row="0" Grid.ColumnSpan="2" Padding="8" x:Name="RootTitleBar" Title="Server information" ShowMinimize="False" ShowMaximize="False" CanMaximize="False" KeyboardNavigation.TabNavigation="None" Icon="pack://application:,,,/Bloxstrap.ico" />

<StackPanel Grid.Row="1" Margin="12">
<TextBlock Text="Instance ID" FontSize="16" FontWeight="Medium" />
<TextBlock Text="{Binding InstanceId, Mode=OneWay}" />
<StackPanel Grid.Row="1" Margin="12">
<TextBlock Text="Instance ID" FontSize="16" FontWeight="Medium" />
<TextBlock Text="{Binding InstanceId, Mode=OneWay}" />

<TextBlock Margin="0,16,0,0" Text="Server location" FontSize="16" FontWeight="Medium" />
<TextBlock Text="{Binding ServerLocation, Mode=OneWay}" />
</StackPanel>
<TextBlock Margin="0,16,0,0" Text="Server location" FontSize="16" FontWeight="Medium" />
<TextBlock Text="{Binding ServerLocation, Mode=OneWay}" />
</StackPanel>

<Border Grid.Row="2" Margin="0,10,0,0" Padding="15" Background="{ui:ThemeResource SolidBackgroundFillColorSecondaryBrush}">
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight" HorizontalAlignment="Right">
<Button MinWidth="100" Content="Copy instance ID" Command="{Binding CopyInstanceIdCommand, Mode=OneTime}" />
<Button Margin="12,0,0,0" MinWidth="100" Content="Close" Command="{Binding CloseWindowCommand, Mode=OneTime}" />
</StackPanel>
</Border>
</Grid>
<Border Grid.Row="2" Margin="0,10,0,0" Padding="15" Background="{ui:ThemeResource SolidBackgroundFillColorSecondaryBrush}">
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight" HorizontalAlignment="Right">
<Button MinWidth="100" Content="Copy instance ID" Command="{Binding CopyInstanceIdCommand, Mode=OneTime}" />
<Button Margin="12,0,0,0" MinWidth="100" Content="Close" Command="{Binding CloseWindowCommand, Mode=OneTime}" />
</StackPanel>
</Border>
</Grid>
</ui:UiWindow>
30 changes: 25 additions & 5 deletions Bloxstrap/UI/NotifyIconWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class NotifyIconWrapper : IDisposable
private DiscordRichPresence? _richPresenceHandler;

private ServerInformation? _serverInformationWindow;

private LogTracer? _logTracerWindow;

EventHandler? _alertClickHandler;

Expand Down Expand Up @@ -58,6 +58,9 @@ public void SetActivityWatcher(RobloxActivity activityWatcher)
_activityWatcher = activityWatcher;
_activityWatcher.OnGameJoin += (_, _) => Task.Run(OnGameJoin);
_activityWatcher.OnGameLeave += OnGameLeave;

if (App.Settings.Prop.OhHeyYouFoundMe && _menuContainer is not null)
_menuContainer.Dispatcher.Invoke(() => _menuContainer.LogTracerMenuItem.Visibility = Visibility.Visible);
}
#endregion

Expand All @@ -69,8 +72,9 @@ public void InitializeContextMenu()

_menuContainer = new();
_menuContainer.Dispatcher.BeginInvoke(_menuContainer.ShowDialog);
_menuContainer.ServerDetailsMenuItem.Click += (_, _) => ShowServerInformationWindow();
_menuContainer.RichPresenceMenuItem.Click += (_, _) => _richPresenceHandler?.SetVisibility(_menuContainer.RichPresenceMenuItem.IsChecked);
_menuContainer.ServerDetailsMenuItem.Click += (_, _) => ShowServerInformationWindow();
_menuContainer.LogTracerMenuItem.Click += (_, _) => ShowLogTracerWindow();
_menuContainer.Closing += (_, _) => App.Logger.WriteLine("[NotifyIconWrapper::NotifyIconWrapper] Context menu container closed");
}

Expand All @@ -84,6 +88,7 @@ public void MouseClickEventHandler(object? sender, System.Windows.Forms.MouseEve
}
#endregion

#region Activity handlers
public async void OnGameJoin()
{
if (_menuContainer is not null)
Expand All @@ -98,14 +103,14 @@ public async void OnGameJoin()

public void OnGameLeave(object? sender, EventArgs e)
{
if (_menuContainer is not null)
_menuContainer.Dispatcher.Invoke(() => _menuContainer.ServerDetailsMenuItem.Visibility = Visibility.Collapsed);
_menuContainer?.Dispatcher.Invoke(() => _menuContainer.ServerDetailsMenuItem.Visibility = Visibility.Collapsed);

if (_serverInformationWindow is not null && _serverInformationWindow.IsVisible)
_serverInformationWindow.Dispatcher.Invoke(_serverInformationWindow.Close);

}
#endregion

#region Window handlers
public void ShowServerInformationWindow()
{
if (_serverInformationWindow is null)
Expand All @@ -120,6 +125,21 @@ public void ShowServerInformationWindow()
_serverInformationWindow.Activate();
}

public void ShowLogTracerWindow()
{
if (_logTracerWindow is null)
{
_logTracerWindow = new LogTracer(_activityWatcher!);
_logTracerWindow.Closed += (_, _) => _logTracerWindow = null;
}

if (!_logTracerWindow.IsVisible)
_logTracerWindow.Show();

_logTracerWindow.Activate();
}
#endregion

public void ShowAlert(string caption, string message, int duration, EventHandler? clickHandler)
{
string id = Guid.NewGuid().ToString()[..8];
Expand Down
30 changes: 30 additions & 0 deletions Bloxstrap/UI/ViewModels/ContextMenu/LogTracerViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Windows;
using System.Windows.Input;

using CommunityToolkit.Mvvm.Input;

namespace Bloxstrap.UI.ViewModels.ContextMenu
{
internal class LogTracerViewModel : NotifyPropertyChangedViewModel
{
private readonly Window _window;
private readonly RobloxActivity _activityWatcher;

public ICommand CloseWindowCommand => new RelayCommand(_window.Close);

public string LogLocation => _activityWatcher.LogFilename;
public string LogContents { get; private set; } = "";

public LogTracerViewModel(Window window, RobloxActivity activityWatcher)
{
_window = window;
_activityWatcher = activityWatcher;

_activityWatcher.OnLogEntry += (_, message) =>
{
LogContents += message += "\r\n";
OnPropertyChanged(nameof(LogContents));
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@

using CommunityToolkit.Mvvm.Input;

using Bloxstrap.UI.Elements.ContextMenu;

namespace Bloxstrap.UI.ViewModels.ContextMenu
{
internal class ServerInformationViewModel : NotifyPropertyChangedViewModel
{
private readonly ServerInformation _window;
private readonly Window _window;
private readonly RobloxActivity _activityWatcher;

public string InstanceId => _activityWatcher.ActivityJobId;
Expand All @@ -18,7 +16,7 @@ internal class ServerInformationViewModel : NotifyPropertyChangedViewModel
public ICommand CopyInstanceIdCommand => new RelayCommand(CopyInstanceId);
public ICommand CloseWindowCommand => new RelayCommand(_window.Close);

public ServerInformationViewModel(ServerInformation window, RobloxActivity activityWatcher)
public ServerInformationViewModel(Window window, RobloxActivity activityWatcher)
{
_window = window;
_activityWatcher = activityWatcher;
Expand Down

0 comments on commit 53a6488

Please sign in to comment.