Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bc99a3f
Avalonia: Add Windows system tray icon with full status parity
GabrielDuf Apr 27, 2026
7439308
Avalonia: Code quality fixes and WinUI parity
GabrielDuf Apr 27, 2026
92e0683
Avalonia: Add CLI argument handler for settings manipulation
GabrielDuf Apr 28, 2026
80d5df5
Avalonia: Run app integrity check at startup
GabrielDuf Apr 28, 2026
4fccd6f
Avalonia: Implement download-only installer operations
GabrielDuf Apr 28, 2026
7da7200
Avalonia: Fix compilation errors in integrity check dialog
GabrielDuf Apr 28, 2026
436157e
Avalonia: Add Create .ps1 script to Package Bundles page
GabrielDuf Apr 28, 2026
f7e0cbd
Avalonia: Add WinGet repair and malfunction detection
GabrielDuf Apr 28, 2026
bdb34da
Avalonia: Show missing dependency install dialogs at startup
GabrielDuf Apr 28, 2026
87b0cfd
Avalonia: Convert inline Window dialogs to proper .axaml views
GabrielDuf Apr 28, 2026
76bf2a4
Avalonia: Match WinUI warning color on integrity violation dialog
GabrielDuf Apr 28, 2026
8a867f2
integrity
GabrielDuf Apr 28, 2026
3b08e0d
missing dependency
GabrielDuf Apr 28, 2026
2167756
Avalonia: Add package screenshots to PackageDetailsWindow
GabrielDuf Apr 28, 2026
46935b3
Avalonia: Add "Close apps before installing" tab to InstallOptionsWindow
GabrielDuf Apr 28, 2026
ba688f6
Avalonia: Show OperationFailedDialog with colored output and retry on…
GabrielDuf Apr 28, 2026
9c692f6
Avalonia: Fix screenshots not displaying — notify SelectedScreenshot …
GabrielDuf Apr 28, 2026
30393ef
Avalonia: Fix Close apps tab strings to match WinUI translation keys
GabrielDuf Apr 28, 2026
daa66b3
Avalonia: Remove Add button from Close apps tab, use comma/Enter as d…
GabrielDuf Apr 28, 2026
810bd6e
fix some issue on windows
GabrielDuf Apr 28, 2026
4e7c882
fixed windows tray icon
GabrielDuf Apr 29, 2026
c77b509
fix import ordering
GabrielDuf Apr 29, 2026
b495160
style formatting
GabrielDuf Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/UniGetUI.Avalonia/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@ public override void OnFrameworkInitializationCompleted()

if (CoreData.WasDaemon)
{
// Start silently: hide the window as soon as Avalonia opens it.
mainWindow.Opened += (_, _) => mainWindow.Hide();
// Start silently: hide the window on first open only.
// Opened fires on every Show() in Avalonia, so we must unsubscribe
// immediately or every ShowFromTray() call would hide the window again.
void HideOnce(object? s, EventArgs e)
{
mainWindow.Opened -= HideOnce;
mainWindow.Hide();
}
mainWindow.Opened += HideOnce;
}

_ = StartupAsync(mainWindow);
Expand Down
221 changes: 221 additions & 0 deletions src/UniGetUI.Avalonia/AvaloniaCliHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
using UniGetUI.Core.Data;
using UniGetUI.Core.Logging;
using UniGetUI.Core.SettingsEngine;
using UniGetUI.Core.SettingsEngine.SecureSettings;
using UniGetUI.Core.Tools;

namespace UniGetUI.Avalonia;

/// <summary>
/// Pre-UI CLI argument handler. Mirrors WinUI's CLIHandler.
/// Methods that return a non-null exit code should cause the process to exit
/// without launching the Avalonia app.
/// </summary>
internal static class AvaloniaCliHandler
{
public const string HELP = "--help";
public const string DAEMON = "--daemon";
public const string NO_CORRUPT_DIALOG = "--no-corrupt-dialog";

public const string IMPORT_SETTINGS = "--import-settings";
public const string EXPORT_SETTINGS = "--export-settings";

public const string ENABLE_SETTING = "--enable-setting";
public const string DISABLE_SETTING = "--disable-setting";
public const string SET_SETTING_VAL = "--set-setting-value";

public const string ENABLE_SECURE_SETTING = "--enable-secure-setting";
public const string DISABLE_SECURE_SETTING = "--disable-secure-setting";
public const string ENABLE_SECURE_SETTING_FOR_USER = SecureSettings.Args.ENABLE_FOR_USER;
public const string DISABLE_SECURE_SETTING_FOR_USER = SecureSettings.Args.DISABLE_FOR_USER;

private enum ExitCode
{
Success = 0,
Failed = -1,
InvalidParameter = -1073741811,
NoSuchFile = -1073741809,
UnknownSettingsKey = -2,
}

/// <summary>
/// Inspect <paramref name="args"/> and, for recognised pre-UI arguments,
/// execute the requested action and return the desired process exit code.
/// Returns null when no pre-UI argument was found and the app should start normally.
/// </summary>
public static int? HandlePreUiArgs(string[] args)
{
if (args.Contains(HELP))
{
CoreTools.Launch("https://github.com/Devolutions/UniGetUI/blob/main/cli-arguments.md#unigetui-command-line-parameters");
return (int)ExitCode.Success;
}

if (args.Contains(IMPORT_SETTINGS))
return ImportSettings(args);

if (args.Contains(EXPORT_SETTINGS))
return ExportSettings(args);

if (args.Contains(ENABLE_SETTING))
return EnableSetting(args);

if (args.Contains(DISABLE_SETTING))
return DisableSetting(args);

if (args.Contains(SET_SETTING_VAL))
return SetSettingsValue(args);

if (args.Contains(ENABLE_SECURE_SETTING))
return EnableSecureSetting(args);

if (args.Contains(DISABLE_SECURE_SETTING))
return DisableSecureSetting(args);

if (args.Contains(ENABLE_SECURE_SETTING_FOR_USER))
return EnableSecureSettingForUser(args);

if (args.Contains(DISABLE_SECURE_SETTING_FOR_USER))
return DisableSecureSettingForUser(args);

return null;
}

private static int ImportSettings(string[] args)
{
int idx = Array.IndexOf(args, IMPORT_SETTINGS);
if (idx < 0 || idx + 1 >= args.Length)
return (int)ExitCode.InvalidParameter;

var file = args[idx + 1].Trim('"').Trim('\'');
if (!File.Exists(file))
return (int)ExitCode.NoSuchFile;

try
{
Settings.ImportFromFile_JSON(file);
return (int)ExitCode.Success;
}
catch (Exception ex)
{
Logger.Error(ex);
return ex.HResult;
}
}

private static int ExportSettings(string[] args)
{
int idx = Array.IndexOf(args, EXPORT_SETTINGS);
if (idx < 0 || idx + 1 >= args.Length)
return (int)ExitCode.InvalidParameter;

var file = args[idx + 1].Trim('"').Trim('\'');
try
{
Settings.ExportToFile_JSON(file);
return (int)ExitCode.Success;
}
catch (Exception ex)
{
Logger.Error(ex);
return ex.HResult;
}
}

private static int EnableSetting(string[] args)
{
int idx = Array.IndexOf(args, ENABLE_SETTING);
if (idx < 0 || idx + 1 >= args.Length)
return (int)ExitCode.InvalidParameter;

if (!Enum.TryParse(args[idx + 1].Trim('"').Trim('\''), out Settings.K key))
return (int)ExitCode.UnknownSettingsKey;

try { Settings.Set(key, true); return (int)ExitCode.Success; }
catch (Exception ex) { return ex.HResult; }
}

private static int DisableSetting(string[] args)
{
int idx = Array.IndexOf(args, DISABLE_SETTING);
if (idx < 0 || idx + 1 >= args.Length)
return (int)ExitCode.InvalidParameter;

if (!Enum.TryParse(args[idx + 1].Trim('"').Trim('\''), out Settings.K key))
return (int)ExitCode.UnknownSettingsKey;

try { Settings.Set(key, false); return (int)ExitCode.Success; }
catch (Exception ex) { return ex.HResult; }
}

private static int SetSettingsValue(string[] args)
{
int idx = Array.IndexOf(args, SET_SETTING_VAL);
if (idx < 0 || idx + 2 >= args.Length)
return (int)ExitCode.InvalidParameter;

if (!Enum.TryParse(args[idx + 1].Trim('"').Trim('\''), out Settings.K key))
return (int)ExitCode.UnknownSettingsKey;

try { Settings.SetValue(key, args[idx + 2]); return (int)ExitCode.Success; }
catch (Exception ex) { return ex.HResult; }
}

private static int EnableSecureSetting(string[] args)
{
int idx = Array.IndexOf(args, ENABLE_SECURE_SETTING);
if (idx < 0 || idx + 1 >= args.Length)
return (int)ExitCode.InvalidParameter;

if (!Enum.TryParse(args[idx + 1].Trim('"').Trim('\''), out SecureSettings.K key))
return (int)ExitCode.UnknownSettingsKey;

try
{
bool ok = SecureSettings.TrySet(key, true).GetAwaiter().GetResult();
return ok ? (int)ExitCode.Success : (int)ExitCode.Failed;
}
catch (Exception ex) { return ex.HResult; }
}

private static int DisableSecureSetting(string[] args)
{
int idx = Array.IndexOf(args, DISABLE_SECURE_SETTING);
if (idx < 0 || idx + 1 >= args.Length)
return (int)ExitCode.InvalidParameter;

if (!Enum.TryParse(args[idx + 1].Trim('"').Trim('\''), out SecureSettings.K key))
return (int)ExitCode.UnknownSettingsKey;

try
{
bool ok = SecureSettings.TrySet(key, false).GetAwaiter().GetResult();
return ok ? (int)ExitCode.Success : (int)ExitCode.Failed;
}
catch (Exception ex) { return ex.HResult; }
}

private static int EnableSecureSettingForUser(string[] args)
{
int idx = Array.IndexOf(args, ENABLE_SECURE_SETTING_FOR_USER);
if (idx < 0 || idx + 2 >= args.Length)
return (int)ExitCode.InvalidParameter;

var user = args[idx + 1].Trim('"').Trim('\'');
var setting = args[idx + 2].Trim('"').Trim('\'');
try { return SecureSettings.ApplyForUser(user, setting, true); }
catch (Exception ex) { return ex.HResult; }
}

private static int DisableSecureSettingForUser(string[] args)
{
int idx = Array.IndexOf(args, DISABLE_SECURE_SETTING_FOR_USER);
if (idx < 0 || idx + 2 >= args.Length)
return (int)ExitCode.InvalidParameter;

var user = args[idx + 1].Trim('"').Trim('\'');
var setting = args[idx + 2].Trim('"').Trim('\'');
try { return SecureSettings.ApplyForUser(user, setting, false); }
catch (Exception ex) { return ex.HResult; }
}
}
Loading
Loading