Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/UniGetUI.Avalonia/Assets/Styles/Styles.WindowsMica.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<SolidColorBrush x:Key="AppDialogPanelBackground" Color="#80FFFFFF"/>
<SolidColorBrush x:Key="AppDialogSubtleBackground" Color="#80FFFFFF"/>
<SolidColorBrush x:Key="AppDialogDarkBackground" Color="#80FFFFFF"/>
<!-- Flyouts / menus / dropdowns / tooltips: DWM Mica backdrop with the card tint over it -->
<!-- Flyouts / menus / dropdowns / tooltips: DWM acrylic backdrop with the card tint over it -->
<SolidColorBrush x:Key="FlyoutPresenterBackground" Color="#80FFFFFF"/>
<SolidColorBrush x:Key="MenuFlyoutPresenterBackground" Color="#80FFFFFF"/>
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="#80FFFFFF"/>
Expand Down Expand Up @@ -61,8 +61,8 @@
<SolidColorBrush x:Key="AppDialogPanelBackground" Color="#662C2C2C"/>
<SolidColorBrush x:Key="AppDialogSubtleBackground" Color="#66393939"/>
<SolidColorBrush x:Key="AppDialogDarkBackground" Color="#66181818"/>
<!-- Flyouts / menus / dropdowns / tooltips: MicaWindowHelper gives the popup window the same
DWM Mica backdrop the app uses; this tint matches the cards so menus read identically -->
<!-- Flyouts / menus / dropdowns / tooltips: MicaWindowHelper gives the popup window a DWM
acrylic backdrop (transient surfaces can't use Mica); this tint matches the cards -->
<SolidColorBrush x:Key="FlyoutPresenterBackground" Color="#662D2D2D"/>
<SolidColorBrush x:Key="MenuFlyoutPresenterBackground" Color="#662D2D2D"/>
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="#662D2D2D"/>
Expand Down
27 changes: 20 additions & 7 deletions src/UniGetUI.Avalonia/Infrastructure/MicaWindowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; // Micasame backdrop as the rest of the app, so menus match
private const int DWMSBT_TRANSIENTWINDOW = 3; // Acrylicfor transient surfaces (menus/flyouts); Mica won't paint on these
private const int DWMWA_COLOR_DEFAULT = unchecked((int)0xFFFFFFFF);

private static bool _acrylicPopupsHooked;
Expand Down Expand Up @@ -69,23 +69,36 @@ 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<PopupRoot>((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<Window>((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)
return;

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));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
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;
Expand Down Expand Up @@ -188,7 +189,7 @@
// ─── Events (replace abstract methods) ───────────────────────────────────
public event Action<ReloadReason>? PackagesLoaded;
public event Action? PackageCountUpdated;
public event Action<IPackage>? ShowingContextMenu;

Check warning on line 192 in src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs

View workflow job for this annotation

GitHub Actions / Linux (Avalonia)

The event 'PackagesPageViewModel.ShowingContextMenu' is never used

Check warning on line 192 in src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs

View workflow job for this annotation

GitHub Actions / test-codebase

The event 'PackagesPageViewModel.ShowingContextMenu' is never used
public event Action? FocusListRequested;

// ─── Events: view-side dialog/navigation requests ─────────────────────────
Expand All @@ -206,6 +207,7 @@
DisableFilterOnQueryChange = data.DisableFilterOnQueryChange;
MegaQueryBoxEnabled = data.MegaQueryBlockEnabled;
DisableReload = data.DisableReload;
LoadsOnStart = !data.DisableAutomaticPackageLoadOnStart;
_showLastCheckedTime = data.ShowLastLoadTime;
NoPackagesText = data.NoPackages_BackgroundText;
NoMatchesText = data.NoMatches_BackgroundText;
Expand Down Expand Up @@ -516,7 +518,14 @@
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);
Expand All @@ -533,7 +542,6 @@
if (!Loader.IsLoading && (!Loader.IsLoaded
|| reason is ReloadReason.External or ReloadReason.Manual or ReloadReason.Automated))
{
Loader.ClearPackages(emitFinishSignal: false);
await Loader.ReloadPackages();
}
}
Expand Down Expand Up @@ -827,7 +835,7 @@
// ─── Subtitle ─────────────────────────────────────────────────────────────
public void UpdateSubtitle()
{
if (Loader.IsLoading)
if (Loader.IsLoading || (LoadsOnStart && !Loader.IsLoaded))
{
Subtitle = _stillLoadingSubtitle;
return;
Expand Down
2 changes: 2 additions & 0 deletions src/UniGetUI.Avalonia/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ protected async Task LoadPackages(ReloadReason reason)
)
)
{
Loader.ClearPackages(emitFinishSignal: false);
await Loader.ReloadPackages();
}
}
Expand Down
Loading