Skip to content

Commit

Permalink
Resource strings hot reload for plugins (only current, valid resources)
Browse files Browse the repository at this point in the history
  • Loading branch information
KimihikoAkayasaki committed Feb 20, 2023
1 parent c097cf0 commit 271c0cb
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
36 changes: 35 additions & 1 deletion Amethyst/Classes/Interfacing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,24 @@ public static bool SetLocalizationResourcesRoot(string path, string guid)
Logger.Info($"[Requested by device with GUID {guid}] " +
"Successfully loaded language resources with key " +
$"\"{AppData.Settings.AppLanguage}\"!");


// Setup string hot reload watchdog
device.AssetsWatcher = new FileSystemWatcher
{
Path = device.LocalizationResourcesRoot.Directory,
NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName |
NotifyFilters.LastWrite | NotifyFilters.DirectoryName,
IncludeSubdirectories = true,
Filter = "*.json",
EnableRaisingEvents = true
};

// Add event handlers : local
device.AssetsWatcher.Changed += device.AssetsChanged;
device.AssetsWatcher.Created += device.AssetsChanged;
device.AssetsWatcher.Deleted += device.AssetsChanged;
device.AssetsWatcher.Renamed += device.AssetsChanged;

return true; // Winning it, yay!
}

Expand All @@ -761,6 +778,23 @@ public static bool SetLocalizationResourcesRoot(string path, string guid)
"Successfully loaded language resources with key " +
$"\"{AppData.Settings.AppLanguage}\"!");

// Setup string hot reload watchdog
service.AssetsWatcher = new FileSystemWatcher
{
Path = service.LocalizationResourcesRoot.Directory,
NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName |
NotifyFilters.LastWrite | NotifyFilters.DirectoryName,
IncludeSubdirectories = true,
Filter = "*.json",
EnableRaisingEvents = true
};

// Add event handlers : local
service.AssetsWatcher.Changed += service.AssetsChanged;
service.AssetsWatcher.Created += service.AssetsChanged;
service.AssetsWatcher.Deleted += service.AssetsChanged;
service.AssetsWatcher.Renamed += service.AssetsChanged;

return true; // Winning it, yay!
}

Expand Down
7 changes: 3 additions & 4 deletions Amethyst/MVVM/PluginHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
using Amethyst.Utils;
using AmethystSupport;
using Microsoft.AppCenter.Crashes;
using Microsoft.UI.Xaml;
using static Amethyst.Classes.Interfacing;

namespace Amethyst.MVVM;
Expand Down Expand Up @@ -481,7 +480,7 @@ public static bool AddPlugin<T>(this ICollection<T> collection, DirectoryInfo it
if (!assemblyCatalog.Parts.Any(x => x.ExportDefinitions
.Any(y => y.ContractName == typeof(ITrackingDevice).FullName ||
y.ContractName == typeof(IServiceEndpoint).FullName))) continue;

collection.Add((T)(object)assemblyCatalog);
return true; // This plugin is probably supported, yay!
}
Expand All @@ -499,7 +498,7 @@ public static bool AddPlugin<T>(this ICollection<T> collection, DirectoryInfo it
TrackingDevices.LoadAttemptedPluginsList.Add(new LoadAttemptedPlugin
{
Name = $"{item.Name}/{fileInfo.Name}",
Error = e.Message, Folder = item.FullName,
Error = $"{e.Message}\n\n{e.StackTrace}", Folder = item.FullName,
Status = TrackingDevices.PluginLoadError.NoPluginDll
});

Expand All @@ -520,7 +519,7 @@ public static bool AddPlugin<T>(this ICollection<T> collection, DirectoryInfo it
TrackingDevices.LoadAttemptedPluginsList.Add(new LoadAttemptedPlugin
{
Name = $"{item.Name}/{fileInfo.Name}",
Error = e.Message, Folder = item.FullName,
Error = $"{e.Message}\n\n{e.StackTrace}", Folder = item.FullName,
Status = TrackingDevices.PluginLoadError.NoPluginDll
});

Expand Down
37 changes: 37 additions & 0 deletions Amethyst/MVVM/ServiceEndpoint.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Numerics;
using System.Threading.Tasks;
using Windows.Data.Json;
using Amethyst.Classes;
using Amethyst.Plugins.Contract;
using Amethyst.Utils;
using System.Linq;

namespace Amethyst.MVVM;

Expand Down Expand Up @@ -113,6 +116,9 @@ public bool AutoCloseAmethyst
// You'll need to provide this to support automatic calibration
public (Vector3 Position, Quaternion Orientation)? HeadsetPose => Service.HeadsetPose;

// Hot reload handler
public FileSystemWatcher AssetsWatcher { get; set; }

// Property changed event
public event PropertyChangedEventHandler PropertyChanged;

Expand Down Expand Up @@ -191,4 +197,35 @@ public void OnPropertyChanged(string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}

public void AssetsChanged(object o, FileSystemEventArgs fileSystemEventArgs)
{
Shared.Main.DispatcherQueue.TryEnqueue(() =>
{
// Hot reload device string resources
Logger.Info($"Service ({Guid}, {Name}) assets have changed, reloading!");
Logger.Info($"What happened: {fileSystemEventArgs.ChangeType}");
Logger.Info($"Where: {fileSystemEventArgs.FullPath} ({fileSystemEventArgs.Name})");
// Sanity check
if (!Shared.Main.MainWindowLoaded) return;
// Reload plugins' language resources
Interfacing.Plugins.SetLocalizationResourcesRoot(
LocalizationResourcesRoot.Directory, Guid);
// Reload everything we can
Shared.Devices.DevicesJointsValid = false;
Service.OnLoad(); // Reload settings
// Force refresh all the valid pages
Shared.Events.RequestInterfaceReload(false);
if (AppData.Settings.ServiceEndpointGuid == Guid)
Interfacing.UpdateServerStatus(); // Refresh
// We're done with our changes now!
Shared.Devices.DevicesJointsValid = true;
});
}
}
33 changes: 33 additions & 0 deletions Amethyst/MVVM/TrackingDevice.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using Windows.Data.Json;
using Amethyst.Classes;
using Amethyst.Plugins.Contract;
using Amethyst.Utils;
using static Amethyst.Classes.Interfacing;

namespace Amethyst.MVVM;
Expand Down Expand Up @@ -113,6 +115,9 @@ public TrackingDevice(string name, string guid, string path, ITrackingDevice dev
// Is the device used as anything, quick check?
public bool IsUsed => IsBase || IsOverride;

// Hot reload handler
public FileSystemWatcher AssetsWatcher { get; set; }

// Property changed event
public event PropertyChangedEventHandler PropertyChanged;

Expand Down Expand Up @@ -202,4 +207,32 @@ public void RefreshWatchHandlers()
Device.TrackedJoints.CollectionChanged -= TrackedJoints_CollectionChanged;
Device.TrackedJoints.CollectionChanged += TrackedJoints_CollectionChanged;
}

public void AssetsChanged(object o, FileSystemEventArgs fileSystemEventArgs)
{
Shared.Main.DispatcherQueue.TryEnqueue(() =>
{
// Hot reload device string resources
Logger.Info($"Device ({Guid}, {Name}) assets have changed, reloading!");
Logger.Info($"What happened: {fileSystemEventArgs.ChangeType}");
Logger.Info($"Where: {fileSystemEventArgs.FullPath} ({fileSystemEventArgs.Name})");
// Sanity check
if (!Shared.Main.MainWindowLoaded) return;
// Reload plugins' language resources
Interfacing.Plugins.SetLocalizationResourcesRoot(
LocalizationResourcesRoot.Directory, Guid);
// Reload everything we can
Shared.Devices.DevicesJointsValid = false;
Device.OnLoad(); // Reload settings
// Force refresh all the valid pages
Shared.Events.RequestInterfaceReload(false);
// We're done with our changes now!
Shared.Devices.DevicesJointsValid = true;
});
}
}

0 comments on commit 271c0cb

Please sign in to comment.