mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Merge branch 'main' into user-pfp-discord-rpc
This commit is contained in:
commit
3855ac68dd
9
Bloxstrap/GlobalCache.cs
Normal file
9
Bloxstrap/GlobalCache.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Bloxstrap
|
||||||
|
{
|
||||||
|
public static class GlobalCache
|
||||||
|
{
|
||||||
|
public static readonly Dictionary<string, Task> PendingTasks = new();
|
||||||
|
|
||||||
|
public static readonly Dictionary<string, string> ServerLocation = new();
|
||||||
|
}
|
||||||
|
}
|
@ -494,7 +494,7 @@ namespace Bloxstrap
|
|||||||
string oldStartPath = Path.Combine(Paths.WindowsStartMenu, "Bloxstrap");
|
string oldStartPath = Path.Combine(Paths.WindowsStartMenu, "Bloxstrap");
|
||||||
|
|
||||||
if (File.Exists(oldDesktopPath))
|
if (File.Exists(oldDesktopPath))
|
||||||
File.Move(oldDesktopPath, DesktopShortcut);
|
File.Move(oldDesktopPath, DesktopShortcut, true);
|
||||||
|
|
||||||
if (Directory.Exists(oldStartPath))
|
if (Directory.Exists(oldStartPath))
|
||||||
{
|
{
|
||||||
|
@ -127,7 +127,6 @@ namespace Bloxstrap.Integrations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: i need to double check how this handles failed game joins (connection error, invalid permissions, etc)
|
|
||||||
private void ReadLogEntry(string entry)
|
private void ReadLogEntry(string entry)
|
||||||
{
|
{
|
||||||
const string LOG_IDENT = "ActivityWatcher::ReadLogEntry";
|
const string LOG_IDENT = "ActivityWatcher::ReadLogEntry";
|
||||||
@ -144,7 +143,17 @@ namespace Bloxstrap.Integrations
|
|||||||
App.Logger.WriteLine(LOG_IDENT, $"Read {_logEntriesRead} log entries");
|
App.Logger.WriteLine(LOG_IDENT, $"Read {_logEntriesRead} log entries");
|
||||||
|
|
||||||
if (entry.Contains(GameLeavingEntry))
|
if (entry.Contains(GameLeavingEntry))
|
||||||
OnAppClose?.Invoke(this, new EventArgs());
|
{
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, "User is back into the desktop app");
|
||||||
|
|
||||||
|
OnAppClose?.Invoke(this, EventArgs.Empty);
|
||||||
|
|
||||||
|
if (Data.PlaceId != 0 && !InGame)
|
||||||
|
{
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, "User appears to be leaving from a cancelled/errored join");
|
||||||
|
Data = new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!InGame && Data.PlaceId == 0)
|
if (!InGame && Data.PlaceId == 0)
|
||||||
{
|
{
|
||||||
@ -183,6 +192,9 @@ namespace Bloxstrap.Integrations
|
|||||||
Data.JobId = match.Groups[1].Value;
|
Data.JobId = match.Groups[1].Value;
|
||||||
Data.MachineAddress = match.Groups[3].Value;
|
Data.MachineAddress = match.Groups[3].Value;
|
||||||
|
|
||||||
|
if (App.Settings.Prop.ShowServerDetails && Data.MachineAddressValid)
|
||||||
|
_ = Data.QueryServerLocation();
|
||||||
|
|
||||||
if (_teleportMarker)
|
if (_teleportMarker)
|
||||||
{
|
{
|
||||||
Data.IsTeleport = true;
|
Data.IsTeleport = true;
|
||||||
@ -195,7 +207,7 @@ namespace Bloxstrap.Integrations
|
|||||||
_reservedTeleportMarker = false;
|
_reservedTeleportMarker = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Joining Game ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})");
|
App.Logger.WriteLine(LOG_IDENT, $"Joining Game ({Data})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!InGame && Data.PlaceId != 0)
|
else if (!InGame && Data.PlaceId != 0)
|
||||||
@ -234,7 +246,7 @@ namespace Bloxstrap.Integrations
|
|||||||
{
|
{
|
||||||
var lastActivity = History.First();
|
var lastActivity = History.First();
|
||||||
|
|
||||||
if (lastActivity is not null && Data.UniverseId == lastActivity.UniverseId && Data.IsTeleport)
|
if (Data.UniverseId == lastActivity.UniverseId && Data.IsTeleport)
|
||||||
Data.RootActivity = lastActivity.RootActivity ?? lastActivity;
|
Data.RootActivity = lastActivity.RootActivity ?? lastActivity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,7 +263,10 @@ namespace Bloxstrap.Integrations
|
|||||||
|
|
||||||
Data.MachineAddress = match.Groups[1].Value;
|
Data.MachineAddress = match.Groups[1].Value;
|
||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Server is UDMUX protected ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})");
|
if (App.Settings.Prop.ShowServerDetails)
|
||||||
|
_ = Data.QueryServerLocation();
|
||||||
|
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, $"Server is UDMUX protected ({Data})");
|
||||||
}
|
}
|
||||||
else if (entry.Contains(GameJoinedEntry))
|
else if (entry.Contains(GameJoinedEntry))
|
||||||
{
|
{
|
||||||
@ -264,7 +279,7 @@ namespace Bloxstrap.Integrations
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Joined Game ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})");
|
App.Logger.WriteLine(LOG_IDENT, $"Joined Game ({Data})");
|
||||||
|
|
||||||
InGame = true;
|
InGame = true;
|
||||||
Data.TimeJoined = DateTime.Now;
|
Data.TimeJoined = DateTime.Now;
|
||||||
@ -278,7 +293,7 @@ namespace Bloxstrap.Integrations
|
|||||||
|
|
||||||
if (entry.Contains(GameDisconnectedEntry))
|
if (entry.Contains(GameDisconnectedEntry))
|
||||||
{
|
{
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Disconnected from Game ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})");
|
App.Logger.WriteLine(LOG_IDENT, $"Disconnected from Game ({Data})");
|
||||||
|
|
||||||
Data.TimeLeft = DateTime.Now;
|
Data.TimeLeft = DateTime.Now;
|
||||||
History.Insert(0, Data);
|
History.Insert(0, Data);
|
||||||
@ -290,7 +305,7 @@ namespace Bloxstrap.Integrations
|
|||||||
}
|
}
|
||||||
else if (entry.Contains(GameTeleportingEntry))
|
else if (entry.Contains(GameTeleportingEntry))
|
||||||
{
|
{
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Initiating teleport to server ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})");
|
App.Logger.WriteLine(LOG_IDENT, $"Initiating teleport to server ({Data})");
|
||||||
_teleportMarker = true;
|
_teleportMarker = true;
|
||||||
}
|
}
|
||||||
else if (_teleportMarker && entry.Contains(GameJoiningReservedServerEntry))
|
else if (_teleportMarker && entry.Contains(GameJoiningReservedServerEntry))
|
||||||
@ -378,44 +393,6 @@ namespace Bloxstrap.Integrations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetServerLocation()
|
|
||||||
{
|
|
||||||
const string LOG_IDENT = "ActivityWatcher::GetServerLocation";
|
|
||||||
|
|
||||||
if (GeolocationCache.ContainsKey(Data.MachineAddress))
|
|
||||||
return GeolocationCache[Data.MachineAddress];
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string location = "";
|
|
||||||
var ipInfo = await Http.GetJson<IPInfoResponse>($"https://ipinfo.io/{Data.MachineAddress}/json");
|
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(ipInfo.City))
|
|
||||||
throw new InvalidHTTPResponseException("Reported city was blank");
|
|
||||||
|
|
||||||
if (ipInfo.City == ipInfo.Region)
|
|
||||||
location = $"{ipInfo.Region}, {ipInfo.Country}";
|
|
||||||
else
|
|
||||||
location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}";
|
|
||||||
|
|
||||||
GeolocationCache[Data.MachineAddress] = location;
|
|
||||||
|
|
||||||
if (!InGame)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {Data.MachineAddress}");
|
|
||||||
App.Logger.WriteException(LOG_IDENT, ex);
|
|
||||||
|
|
||||||
Frontend.ShowMessageBox($"{Strings.ActivityWatcher_LocationQueryFailed}\n\n{ex.Message}", MessageBoxImage.Warning);
|
|
||||||
|
|
||||||
return "?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
@ -38,6 +39,8 @@ namespace Bloxstrap.Models
|
|||||||
|
|
||||||
public string UserId { get; set; } = String.Empty;
|
public string UserId { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public bool MachineAddressValid => !String.IsNullOrEmpty(MachineAddress) && !MachineAddress.StartsWith("10.");
|
||||||
|
|
||||||
public bool IsTeleport { get; set; } = false;
|
public bool IsTeleport { get; set; } = false;
|
||||||
|
|
||||||
public ServerType ServerType { get; set; } = ServerType.Public;
|
public ServerType ServerType { get; set; } = ServerType.Public;
|
||||||
@ -85,6 +88,55 @@ namespace Bloxstrap.Models
|
|||||||
return deeplink;
|
return deeplink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<string> QueryServerLocation()
|
||||||
|
{
|
||||||
|
const string LOG_IDENT = "ActivityData::QueryServerLocation";
|
||||||
|
|
||||||
|
if (!MachineAddressValid)
|
||||||
|
throw new InvalidOperationException($"Machine address is invalid ({MachineAddress})");
|
||||||
|
|
||||||
|
if (GlobalCache.PendingTasks.TryGetValue(MachineAddress, out Task? task))
|
||||||
|
await task;
|
||||||
|
|
||||||
|
if (GlobalCache.ServerLocation.TryGetValue(MachineAddress, out string? location))
|
||||||
|
return location;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
location = "";
|
||||||
|
var ipInfoTask = Http.GetJson<IPInfoResponse>($"https://ipinfo.io/{MachineAddress}/json");
|
||||||
|
|
||||||
|
GlobalCache.PendingTasks.Add(MachineAddress, ipInfoTask);
|
||||||
|
|
||||||
|
var ipInfo = await ipInfoTask;
|
||||||
|
|
||||||
|
GlobalCache.PendingTasks.Remove(MachineAddress);
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(ipInfo.City))
|
||||||
|
throw new InvalidHTTPResponseException("Reported city was blank");
|
||||||
|
|
||||||
|
if (ipInfo.City == ipInfo.Region)
|
||||||
|
location = $"{ipInfo.Region}, {ipInfo.Country}";
|
||||||
|
else
|
||||||
|
location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}";
|
||||||
|
|
||||||
|
GlobalCache.ServerLocation[MachineAddress] = location;
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {MachineAddress}");
|
||||||
|
App.Logger.WriteException(LOG_IDENT, ex);
|
||||||
|
|
||||||
|
Frontend.ShowMessageBox($"{Strings.ActivityWatcher_LocationQueryFailed}\n\n{ex.Message}", MessageBoxImage.Warning);
|
||||||
|
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => $"{PlaceId}/{JobId}";
|
||||||
|
|
||||||
private void RejoinServer()
|
private void RejoinServer()
|
||||||
{
|
{
|
||||||
string playerPath = Path.Combine(Paths.Versions, App.State.Prop.PlayerVersionGuid, "RobloxPlayerBeta.exe");
|
string playerPath = Path.Combine(Paths.Versions, App.State.Prop.PlayerVersionGuid, "RobloxPlayerBeta.exe");
|
||||||
|
47
Bloxstrap/Resources/Strings.Designer.cs
generated
47
Bloxstrap/Resources/Strings.Designer.cs
generated
@ -719,15 +719,6 @@ namespace Bloxstrap.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Loading, please wait....
|
|
||||||
/// </summary>
|
|
||||||
public static string ContextMenu_ServerInformation_Loading {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ContextMenu.ServerInformation.Loading", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Location.
|
/// Looks up a localized string similar to Location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -2727,7 +2718,25 @@ namespace Bloxstrap.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running..
|
/// Looks up a localized string similar to When in-game, you'll be able to see where your server is located via [ipinfo.io]({0})..
|
||||||
|
/// </summary>
|
||||||
|
public static string Menu_Integrations_QueryServerLocation_Description {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Menu.Integrations.QueryServerLocation.Description", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Query server location.
|
||||||
|
/// </summary>
|
||||||
|
public static string Menu_Integrations_QueryServerLocation_Title {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Menu.Integrations.QueryServerLocation.Title", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running. [Find out more]({0})..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Menu_Integrations_RequiresActivityTracking {
|
public static string Menu_Integrations_RequiresActivityTracking {
|
||||||
get {
|
get {
|
||||||
@ -2753,24 +2762,6 @@ namespace Bloxstrap.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to When you join a game, you'll be notified of where your server's located. Won't show in fullscreen..
|
|
||||||
/// </summary>
|
|
||||||
public static string Menu_Integrations_ShowServerDetails_Description {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Menu.Integrations.ShowServerDetails.Description", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to See server location when joining a game.
|
|
||||||
/// </summary>
|
|
||||||
public static string Menu_Integrations_ShowServerDetails_Title {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Menu.Integrations.ShowServerDetails.Title", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Integrations.
|
/// Looks up a localized string similar to Integrations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -268,9 +268,6 @@ Your ReShade configuration files will still be saved, and you can locate them by
|
|||||||
<data name="ContextMenu.ServerInformation.InstanceId" xml:space="preserve">
|
<data name="ContextMenu.ServerInformation.InstanceId" xml:space="preserve">
|
||||||
<value>Instance ID</value>
|
<value>Instance ID</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContextMenu.ServerInformation.Loading" xml:space="preserve">
|
|
||||||
<value>Loading, please wait...</value>
|
|
||||||
</data>
|
|
||||||
<data name="ContextMenu.ServerInformation.Location" xml:space="preserve">
|
<data name="ContextMenu.ServerInformation.Location" xml:space="preserve">
|
||||||
<value>Location</value>
|
<value>Location</value>
|
||||||
</data>
|
</data>
|
||||||
@ -761,7 +758,7 @@ Selecting 'No' will ignore this warning and continue installation.</value>
|
|||||||
<value>Enable activity tracking</value>
|
<value>Enable activity tracking</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Menu.Integrations.RequiresActivityTracking" xml:space="preserve">
|
<data name="Menu.Integrations.RequiresActivityTracking" xml:space="preserve">
|
||||||
<value>This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running.</value>
|
<value>This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running. [Find out more]({0}).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Menu.Integrations.ShowGameActivity.Description" xml:space="preserve">
|
<data name="Menu.Integrations.ShowGameActivity.Description" xml:space="preserve">
|
||||||
<value>The Roblox game you're playing will be shown on your Discord profile. [Not working?]({0})</value>
|
<value>The Roblox game you're playing will be shown on your Discord profile. [Not working?]({0})</value>
|
||||||
@ -769,11 +766,11 @@ Selecting 'No' will ignore this warning and continue installation.</value>
|
|||||||
<data name="Menu.Integrations.ShowGameActivity.Title" xml:space="preserve">
|
<data name="Menu.Integrations.ShowGameActivity.Title" xml:space="preserve">
|
||||||
<value>Show game activity</value>
|
<value>Show game activity</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Menu.Integrations.ShowServerDetails.Description" xml:space="preserve">
|
<data name="Menu.Integrations.QueryServerLocation.Description" xml:space="preserve">
|
||||||
<value>When you join a game, you'll be notified of where your server's located. Won't show in fullscreen.</value>
|
<value>When in-game, you'll be able to see where your server is located via [ipinfo.io]({0}).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Menu.Integrations.ShowServerDetails.Title" xml:space="preserve">
|
<data name="Menu.Integrations.QueryServerLocation.Title" xml:space="preserve">
|
||||||
<value>See server location when joining a game</value>
|
<value>Query server location</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Menu.Integrations.Title" xml:space="preserve">
|
<data name="Menu.Integrations.Title" xml:space="preserve">
|
||||||
<value>Integrations</value>
|
<value>Integrations</value>
|
||||||
|
@ -28,6 +28,8 @@ namespace Bloxstrap.UI.Elements.ContextMenu
|
|||||||
|
|
||||||
private ServerInformation? _serverInformationWindow;
|
private ServerInformation? _serverInformationWindow;
|
||||||
|
|
||||||
|
private ServerHistory? _gameHistoryWindow;
|
||||||
|
|
||||||
public MenuContainer(Watcher watcher)
|
public MenuContainer(Watcher watcher)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@ -51,14 +53,14 @@ namespace Bloxstrap.UI.Elements.ContextMenu
|
|||||||
{
|
{
|
||||||
if (_serverInformationWindow is null)
|
if (_serverInformationWindow is null)
|
||||||
{
|
{
|
||||||
_serverInformationWindow = new ServerInformation(_watcher);
|
_serverInformationWindow = new(_watcher);
|
||||||
_serverInformationWindow.Closed += (_, _) => _serverInformationWindow = null;
|
_serverInformationWindow.Closed += (_, _) => _serverInformationWindow = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_serverInformationWindow.IsVisible)
|
if (!_serverInformationWindow.IsVisible)
|
||||||
_serverInformationWindow.Show();
|
_serverInformationWindow.ShowDialog();
|
||||||
|
else
|
||||||
_serverInformationWindow.Activate();
|
_serverInformationWindow.Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ActivityWatcher_OnLogOpen(object? sender, EventArgs e) =>
|
public void ActivityWatcher_OnLogOpen(object? sender, EventArgs e) =>
|
||||||
@ -135,7 +137,16 @@ namespace Bloxstrap.UI.Elements.ContextMenu
|
|||||||
if (_activityWatcher is null)
|
if (_activityWatcher is null)
|
||||||
throw new ArgumentNullException(nameof(_activityWatcher));
|
throw new ArgumentNullException(nameof(_activityWatcher));
|
||||||
|
|
||||||
new ServerHistory(_activityWatcher).ShowDialog();
|
if (_gameHistoryWindow is null)
|
||||||
|
{
|
||||||
|
_gameHistoryWindow = new(_activityWatcher);
|
||||||
|
_gameHistoryWindow.Closed += (_, _) => _gameHistoryWindow = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_gameHistoryWindow.IsVisible)
|
||||||
|
_gameHistoryWindow.ShowDialog();
|
||||||
|
else
|
||||||
|
_gameHistoryWindow.Activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,14 +46,14 @@
|
|||||||
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0,0,16,12" VerticalAlignment="Center" Text="{x:Static resources:Strings.ContextMenu_ServerInformation_InstanceId}" />
|
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0,0,16,12" VerticalAlignment="Center" Text="{x:Static resources:Strings.ContextMenu_ServerInformation_InstanceId}" />
|
||||||
<TextBlock Grid.Row="1" Grid.Column="1" Foreground="{DynamicResource TextFillColorTertiaryBrush}" Text="{Binding InstanceId, Mode=OneWay}" />
|
<TextBlock Grid.Row="1" Grid.Column="1" Foreground="{DynamicResource TextFillColorTertiaryBrush}" Text="{Binding InstanceId, Mode=OneWay}" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,0,16,12" VerticalAlignment="Center" Text="{x:Static resources:Strings.ContextMenu_ServerInformation_Location}" />
|
<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,0,16,12" VerticalAlignment="Center" Text="{x:Static resources:Strings.ContextMenu_ServerInformation_Location}" Visibility="{Binding ServerLocationVisibility, Mode=OneTime}" />
|
||||||
<TextBlock Grid.Row="2" Grid.Column="1" Foreground="{DynamicResource TextFillColorTertiaryBrush}" Text="{Binding ServerLocation, Mode=OneWay}" />
|
<TextBlock Grid.Row="2" Grid.Column="1" Foreground="{DynamicResource TextFillColorTertiaryBrush}" Text="{Binding ServerLocation, Mode=OneWay}" Visibility="{Binding ServerLocationVisibility, Mode=OneTime}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Border Grid.Row="2" Padding="15" Background="{ui:ThemeResource SolidBackgroundFillColorSecondaryBrush}">
|
<Border Grid.Row="2" Padding="15" Background="{ui:ThemeResource SolidBackgroundFillColorSecondaryBrush}">
|
||||||
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight" HorizontalAlignment="Right">
|
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight" HorizontalAlignment="Right">
|
||||||
<Button MinWidth="100" Content="{x:Static resources:Strings.ContextMenu_ServerInformation_CopyInstanceId}" Command="{Binding CopyInstanceIdCommand, Mode=OneTime}" />
|
<Button MinWidth="100" Content="{x:Static resources:Strings.ContextMenu_ServerInformation_CopyInstanceId}" Command="{Binding CopyInstanceIdCommand, Mode=OneTime}" />
|
||||||
<Button Margin="12,0,0,0" MinWidth="100" Content="{x:Static resources:Strings.Common_Close}" Command="{Binding CloseWindowCommand, Mode=OneTime}" />
|
<Button Margin="12,0,0,0" MinWidth="100" Content="{x:Static resources:Strings.Common_Close}" IsCancel="True" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -24,11 +24,7 @@ namespace Bloxstrap.UI.Elements.ContextMenu
|
|||||||
{
|
{
|
||||||
public ServerInformation(Watcher watcher)
|
public ServerInformation(Watcher watcher)
|
||||||
{
|
{
|
||||||
var viewModel = new ServerInformationViewModel(watcher);
|
DataContext = new ServerInformationViewModel(watcher);
|
||||||
|
|
||||||
viewModel.RequestCloseEvent += (_, _) => Close();
|
|
||||||
|
|
||||||
DataContext = viewModel;
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,9 @@
|
|||||||
</controls:OptionControl>
|
</controls:OptionControl>
|
||||||
|
|
||||||
<controls:OptionControl
|
<controls:OptionControl
|
||||||
Header="{x:Static resources:Strings.Menu_Integrations_ShowServerDetails_Title}"
|
Header="{x:Static resources:Strings.Menu_Integrations_QueryServerLocation_Title}"
|
||||||
Description="{x:Static resources:Strings.Menu_Integrations_ShowServerDetails_Description}"
|
Description="{Binding Source={x:Static resources:Strings.Menu_Integrations_QueryServerLocation_Description}, Converter={StaticResource StringFormatConverter}, ConverterParameter='https://ipinfo.io'}"
|
||||||
|
HelpLink="https://github.com/pizzaboxer/bloxstrap/wiki/What-is-activity-tracking%3F#server-location-querying"
|
||||||
IsEnabled="{Binding InnerContent.IsChecked, ElementName=ActivityTrackingOption, Mode=OneWay}">
|
IsEnabled="{Binding InnerContent.IsChecked, ElementName=ActivityTrackingOption, Mode=OneWay}">
|
||||||
<ui:ToggleSwitch IsChecked="{Binding ShowServerDetailsEnabled, Mode=TwoWay}" />
|
<ui:ToggleSwitch IsChecked="{Binding ShowServerDetailsEnabled, Mode=TwoWay}" />
|
||||||
</controls:OptionControl>
|
</controls:OptionControl>
|
||||||
@ -40,7 +41,7 @@
|
|||||||
</controls:OptionControl>
|
</controls:OptionControl>
|
||||||
|
|
||||||
<TextBlock Text="{x:Static resources:Strings.Common_DiscordRichPresence}" FontSize="20" FontWeight="Medium" Margin="0,16,0,0" />
|
<TextBlock Text="{x:Static resources:Strings.Common_DiscordRichPresence}" FontSize="20" FontWeight="Medium" Margin="0,16,0,0" />
|
||||||
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_RequiresActivityTracking}" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
<controls:MarkdownTextBlock MarkdownText="{Binding Source={x:Static resources:Strings.Menu_Integrations_RequiresActivityTracking}, Converter={StaticResource StringFormatConverter}, ConverterParameter='https://github.com/pizzaboxer/bloxstrap/wiki/What-is-activity-tracking%3F#discord-rich-presence'}" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||||
|
|
||||||
<controls:OptionControl
|
<controls:OptionControl
|
||||||
Header="{x:Static resources:Strings.Menu_Integrations_ShowGameActivity_Title}"
|
Header="{x:Static resources:Strings.Menu_Integrations_ShowGameActivity_Title}"
|
||||||
|
@ -26,7 +26,7 @@ namespace Bloxstrap.UI
|
|||||||
|
|
||||||
_watcher = watcher;
|
_watcher = watcher;
|
||||||
|
|
||||||
_notifyIcon = new()
|
_notifyIcon = new(new System.ComponentModel.Container())
|
||||||
{
|
{
|
||||||
Icon = Properties.Resources.IconBloxstrap,
|
Icon = Properties.Resources.IconBloxstrap,
|
||||||
Text = App.ProjectName,
|
Text = App.ProjectName,
|
||||||
@ -35,7 +35,7 @@ namespace Bloxstrap.UI
|
|||||||
|
|
||||||
_notifyIcon.MouseClick += MouseClickEventHandler;
|
_notifyIcon.MouseClick += MouseClickEventHandler;
|
||||||
|
|
||||||
if (_activityWatcher is not null)
|
if (_activityWatcher is not null && App.Settings.Prop.ShowServerDetails)
|
||||||
_activityWatcher.OnGameJoin += OnGameJoin;
|
_activityWatcher.OnGameJoin += OnGameJoin;
|
||||||
|
|
||||||
_menuContainer = new(_watcher);
|
_menuContainer = new(_watcher);
|
||||||
@ -59,7 +59,7 @@ namespace Bloxstrap.UI
|
|||||||
if (_activityWatcher is null)
|
if (_activityWatcher is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string serverLocation = await _activityWatcher.GetServerLocation();
|
string serverLocation = await _activityWatcher.Data.QueryServerLocation();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(serverLocation))
|
if (string.IsNullOrEmpty(serverLocation))
|
||||||
return;
|
return;
|
||||||
@ -81,6 +81,7 @@ namespace Bloxstrap.UI
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
// we may need to create our own handler for this, because this sorta sucks
|
||||||
public void ShowAlert(string caption, string message, int duration, EventHandler? clickHandler)
|
public void ShowAlert(string caption, string message, int duration, EventHandler? clickHandler)
|
||||||
{
|
{
|
||||||
string id = Guid.NewGuid().ToString()[..8];
|
string id = Guid.NewGuid().ToString()[..8];
|
||||||
|
@ -36,8 +36,7 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
|||||||
|
|
||||||
if (entries.Any())
|
if (entries.Any())
|
||||||
{
|
{
|
||||||
// TODO: this will duplicate universe ids
|
string universeIds = String.Join(',', entries.GroupBy(x => x.UniverseId).Select(x => x.First()));
|
||||||
string universeIds = String.Join(',', entries.Select(x => x.UniverseId));
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -13,27 +13,28 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
|||||||
|
|
||||||
public string ServerType => _activityWatcher.Data.ServerType.ToTranslatedString();
|
public string ServerType => _activityWatcher.Data.ServerType.ToTranslatedString();
|
||||||
|
|
||||||
public string ServerLocation { get; private set; } = Strings.ContextMenu_ServerInformation_Loading;
|
public string ServerLocation { get; private set; } = Strings.Common_Loading;
|
||||||
|
|
||||||
|
public Visibility ServerLocationVisibility => App.Settings.Prop.ShowServerDetails ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
public ICommand CopyInstanceIdCommand => new RelayCommand(CopyInstanceId);
|
public ICommand CopyInstanceIdCommand => new RelayCommand(CopyInstanceId);
|
||||||
|
|
||||||
public ICommand CloseWindowCommand => new RelayCommand(RequestClose);
|
|
||||||
|
|
||||||
public EventHandler? RequestCloseEvent;
|
public EventHandler? RequestCloseEvent;
|
||||||
|
|
||||||
public ServerInformationViewModel(Watcher watcher)
|
public ServerInformationViewModel(Watcher watcher)
|
||||||
{
|
{
|
||||||
_activityWatcher = watcher.ActivityWatcher!;
|
_activityWatcher = watcher.ActivityWatcher!;
|
||||||
|
|
||||||
Task.Run(async () =>
|
if (ServerLocationVisibility == Visibility.Visible)
|
||||||
{
|
QueryServerLocation();
|
||||||
ServerLocation = await _activityWatcher.GetServerLocation();
|
}
|
||||||
OnPropertyChanged(nameof(ServerLocation));
|
|
||||||
});
|
public async void QueryServerLocation()
|
||||||
|
{
|
||||||
|
ServerLocation = await _activityWatcher.Data.QueryServerLocation();
|
||||||
|
OnPropertyChanged(nameof(ServerLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CopyInstanceId() => Clipboard.SetDataObject(InstanceId);
|
private void CopyInstanceId() => Clipboard.SetDataObject(InstanceId);
|
||||||
|
|
||||||
private void RequestClose() => RequestCloseEvent?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
namespace Bloxstrap.UI.ViewModels.Installer
|
namespace Bloxstrap.UI.ViewModels.Installer
|
||||||
{
|
{
|
||||||
// TODO: administrator check?
|
|
||||||
public class WelcomeViewModel : NotifyPropertyChangedViewModel
|
public class WelcomeViewModel : NotifyPropertyChangedViewModel
|
||||||
{
|
{
|
||||||
// formatting is done here instead of in xaml, it's just a bit easier
|
// formatting is done here instead of in xaml, it's just a bit easier
|
||||||
|
Loading…
Reference in New Issue
Block a user