tray: --import-profile merges a profile document into the user config
RioJoy.Tray --import-profile <profile.json> merges a single-profile document (a repo's profiles/*.json) into %APPDATA%\RIOJoy\config.json via ConfigStore.ImportProfile: same-name profiles are replaced in place (FindProfile's case-insensitive convention), everything else appended, all other config content preserved. Refuses (exit 3) while a tray instance is running - a live tray rewrites the config from memory and would silently discard the import. Documents that a Name must be stated in the file itself: RioProfile defaults Name to 'Unnamed', so the import checks the raw JSON, not the deserialized object. This is the profile install story for bench machines and pods (previously: hand-paste into the Profiles array). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using RioJoy.Core.Profiles;
|
||||
|
||||
namespace RioJoy.Tray;
|
||||
|
||||
internal static class Program
|
||||
@@ -12,18 +14,63 @@ internal static class Program
|
||||
/// Entry point. RIOJoy runs as a background tray application with no main
|
||||
/// window: an ApplicationContext owns the NotifyIcon and the runtime, so the
|
||||
/// message loop stays alive while the only UI is the tray icon and its menu.
|
||||
///
|
||||
/// <para><c>--import-profile <profile.json></c> merges a single-profile
|
||||
/// document (a repo's <c>profiles/*.json</c>) into this user's config and
|
||||
/// exits without starting the tray. Output goes to stdout/stderr, which a
|
||||
/// GUI-subsystem exe only delivers when redirected — check the exit code
|
||||
/// (0 ok, 1 failed, 2 usage, 3 tray running) when scripting it.</para>
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void Main()
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
if (args.Length >= 1 && string.Equals(args[0], "--import-profile", StringComparison.OrdinalIgnoreCase))
|
||||
return ImportProfile(args);
|
||||
|
||||
using var instance = new Mutex(initiallyOwned: true, SingleInstanceMutex, out bool createdNew);
|
||||
if (!createdNew)
|
||||
return; // another RIOJoy is already running in this session
|
||||
return 0; // another RIOJoy is already running in this session
|
||||
|
||||
// net48 has no source-generated ApplicationConfiguration.Initialize();
|
||||
// do the equivalent setup directly.
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new TrayApplicationContext());
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int ImportProfile(string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
Console.Error.WriteLine("usage: RioJoy.Tray --import-profile <profile.json>");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// A running tray holds the config in memory and rewrites it on its own
|
||||
// saves, which would silently discard this import — refuse instead.
|
||||
// (OpenExisting + catch rather than TryOpenExisting: net40 lacks the Try form.)
|
||||
try
|
||||
{
|
||||
using Mutex running = Mutex.OpenExisting(SingleInstanceMutex);
|
||||
Console.Error.WriteLine("RIOJoy is running in this session - quit it from the tray menu, import, then relaunch.");
|
||||
return 3;
|
||||
}
|
||||
catch (WaitHandleCannotBeOpenedException)
|
||||
{
|
||||
// not running — proceed
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProfileImportResult result = ConfigStore.ImportProfile(TrayApplicationContext.ConfigPath, args[1]);
|
||||
Console.WriteLine($"{(result.Replaced ? "Replaced" : "Added")} profile '{result.Name}' in {TrayApplicationContext.ConfigPath}");
|
||||
return 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"import failed: {ex.Message}");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace RioJoy.Tray;
|
||||
/// </summary>
|
||||
internal sealed class TrayApplicationContext : ApplicationContext
|
||||
{
|
||||
private static readonly string ConfigPath =
|
||||
// Internal so Program's --import-profile writes the same store the tray reads.
|
||||
internal static readonly string ConfigPath =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RIOJoy", "config.json");
|
||||
|
||||
private static readonly TimeSpan PollInterval = TimeSpan.FromSeconds(1);
|
||||
|
||||
Reference in New Issue
Block a user