diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.WindowsMica.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.WindowsMica.axaml
index 6d44525f10..bce364e4f6 100644
--- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.WindowsMica.axaml
+++ b/src/UniGetUI.Avalonia/Assets/Styles/Styles.WindowsMica.axaml
@@ -25,7 +25,7 @@
-
+
@@ -61,8 +61,8 @@
-
+
diff --git a/src/UniGetUI.Avalonia/Infrastructure/MicaWindowHelper.cs b/src/UniGetUI.Avalonia/Infrastructure/MicaWindowHelper.cs
index 0f85fd8ebe..7987e2a697 100644
--- a/src/UniGetUI.Avalonia/Infrastructure/MicaWindowHelper.cs
+++ b/src/UniGetUI.Avalonia/Infrastructure/MicaWindowHelper.cs
@@ -21,7 +21,7 @@ internal static class MicaWindowHelper
private const int DWMWA_BORDER_COLOR = 34;
private const int DWMWA_SYSTEMBACKDROP_TYPE = 38;
private const int DWMWCP_ROUND = 2;
- private const int DWMSBT_MAINWINDOW = 2; // Mica — same backdrop as the rest of the app, so menus match
+ private const int DWMSBT_TRANSIENTWINDOW = 3; // Acrylic — for transient surfaces (menus/flyouts); Mica won't paint on these
private const int DWMWA_COLOR_DEFAULT = unchecked((int)0xFFFFFFFF);
private static bool _acrylicPopupsHooked;
@@ -69,15 +69,28 @@ public static void EnableAcrylicPopups()
return;
_acrylicPopupsHooked = true;
- // Every flyout/menu/tooltip/combo popup is hosted in a PopupRoot; style it as it loads.
+ // In-app flyouts/menus/tooltips/combo popups are hosted in a PopupRoot; style each as it loads.
Control.LoadedEvent.AddClassHandler((root, _) => ApplyAcrylicToPopup(root));
+
+ // The system-tray context menu is NOT a PopupRoot — Avalonia hosts it in its own Window
+ // (Avalonia.Win32.TrayIconImpl.TrayPopupRoot), so it misses the handler above and would
+ // render with no backdrop (transparent over the desktop). Catch it by type name and apply
+ // the same acrylic treatment. The other Windows (MainWindow/dialogs) are handled via Apply().
+ Control.LoadedEvent.AddClassHandler((win, _) =>
+ {
+ if (win.GetType().Name == "TrayPopupRoot")
+ ApplyAcrylicToPopup(win);
+ });
}
- private static void ApplyAcrylicToPopup(PopupRoot root)
+ private static void ApplyAcrylicToPopup(TopLevel root)
{
- // Transparent surface so the DWM acrylic shows; the presenter backgrounds are also
- // transparent (Styles.WindowsMica) so only the acrylic + menu items are painted.
- root.TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent };
+ // Request acrylic (not Transparent): the Transparent level makes a layered window, and DWM
+ // system backdrops never paint on those — so the popup ended up fully see-through with only
+ // the presenter tint, unreadable when shown over the desktop (e.g. the tray menu). AcrylicBlur
+ // gives a composited window DWM can actually fill. This path only runs when Mica is enabled
+ // (Win11 + transparency effects), so acrylic is always available here.
+ root.TransparencyLevelHint = new[] { WindowTransparencyLevel.AcrylicBlur, WindowTransparencyLevel.Blur };
root.Background = Brushes.Transparent;
if (root.TryGetPlatformHandle()?.Handle is not { } handle || handle == 0)
@@ -85,7 +98,7 @@ private static void ApplyAcrylicToPopup(PopupRoot root)
int corner = DWMWCP_ROUND;
NativeMethods.DwmSetWindowAttribute(handle, DWMWA_WINDOW_CORNER_PREFERENCE, ref corner, sizeof(int));
- int backdrop = DWMSBT_MAINWINDOW;
+ int backdrop = DWMSBT_TRANSIENTWINDOW;
NativeMethods.DwmSetWindowAttribute(handle, DWMWA_SYSTEMBACKDROP_TYPE, ref backdrop, sizeof(int));
}
diff --git a/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs b/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs
index 310e46ea43..c5b106bdea 100644
--- a/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs
+++ b/src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs
@@ -126,6 +126,7 @@ partial void OnIsFilterPaneOpenChanged(bool value)
public readonly bool MegaQueryBoxEnabled;
public readonly bool DisableFilterOnQueryChange;
public readonly bool DisableReload;
+ public readonly bool LoadsOnStart;
public readonly bool RoleIsUpdateLike;
public bool SimilarSearchEnabled { get; private set; }
public readonly string NoPackagesText;
@@ -206,6 +207,7 @@ public PackagesPageViewModel(PackagesPageData data)
DisableFilterOnQueryChange = data.DisableFilterOnQueryChange;
MegaQueryBoxEnabled = data.MegaQueryBlockEnabled;
DisableReload = data.DisableReload;
+ LoadsOnStart = !data.DisableAutomaticPackageLoadOnStart;
_showLastCheckedTime = data.ShowLastLoadTime;
NoPackagesText = data.NoPackages_BackgroundText;
NoMatchesText = data.NoMatches_BackgroundText;
@@ -516,7 +518,14 @@ public void FilterPackages(bool fromQuery = false)
UpdateSubtitle();
PackageCountUpdated?.Invoke();
- if (FilteredPackages.Count == 0)
+ bool loadingOrPending = Loader.IsLoading || (LoadsOnStart && !Loader.IsLoaded);
+
+ if (loadingOrPending && FilteredPackages.Count == 0)
+ {
+ BackgroundText = _stillLoadingSubtitle;
+ BackgroundTextVisible = true;
+ }
+ else if (FilteredPackages.Count == 0)
{
BackgroundText = string.IsNullOrWhiteSpace(query) ? NoPackagesText : NoMatchesText;
BackgroundTextVisible = !MegaQueryBoxEnabled || !string.IsNullOrWhiteSpace(query);
@@ -533,7 +542,6 @@ public async Task LoadPackages(ReloadReason reason = ReloadReason.External)
if (!Loader.IsLoading && (!Loader.IsLoaded
|| reason is ReloadReason.External or ReloadReason.Manual or ReloadReason.Automated))
{
- Loader.ClearPackages(emitFinishSignal: false);
await Loader.ReloadPackages();
}
}
@@ -827,7 +835,7 @@ public void UpdatePackageCount()
// ─── Subtitle ─────────────────────────────────────────────────────────────
public void UpdateSubtitle()
{
- if (Loader.IsLoading)
+ if (Loader.IsLoading || (LoadsOnStart && !Loader.IsLoaded))
{
Subtitle = _stillLoadingSubtitle;
return;
diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml
index fa60f3d359..32f70d8a04 100644
--- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml
+++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml
@@ -362,6 +362,8 @@
FontSize="15"
CornerRadius="0"
BorderThickness="0"
+ VerticalContentAlignment="Center"
+ Padding="8,0,4,0"
Background="Transparent"
PlaceholderText="{Binding GlobalSearchPlaceholder}"
IsEnabled="{Binding GlobalSearchEnabled}"
diff --git a/src/UniGetUI.PackageEngine.PackageLoader/AbstractPackageLoader.cs b/src/UniGetUI.PackageEngine.PackageLoader/AbstractPackageLoader.cs
index ad85de9a73..be5139222b 100644
--- a/src/UniGetUI.PackageEngine.PackageLoader/AbstractPackageLoader.cs
+++ b/src/UniGetUI.PackageEngine.PackageLoader/AbstractPackageLoader.cs
@@ -144,12 +144,17 @@ public virtual async Task ReloadPackages()
return;
}
- ClearPackages(emitFinishSignal: false);
LoadOperationIdentifier = new Random().Next();
int current_identifier = LoadOperationIdentifier;
IsLoading = true;
StartedLoading?.Invoke(this, EventArgs.Empty);
+ // Clear packages only after signaling the load started, so the UI shows the
+ // loading state instead of briefly flashing the "no packages found" message.
+ PackageReference.Clear();
+ IsLoaded = false;
+ InvokePackagesChangedEvent(false, [], []);
+
if (REQUIRES_INTERNET)
{
await CoreTools.WaitForInternetConnection();
diff --git a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs
index df6e550490..a4443af0af 100644
--- a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs
+++ b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs
@@ -697,7 +697,6 @@ protected async Task LoadPackages(ReloadReason reason)
)
)
{
- Loader.ClearPackages(emitFinishSignal: false);
await Loader.ReloadPackages();
}
}