Skip to content

Fix 22 bugs: SMTC crashes, mixer leaks/races, seekbar freeze, settings leak, UIA stalls, OSD, startup - #1109

Closed
frans15-2006 wants to merge 99 commits into
unchihugo:masterfrom
frans15-2006:master
Closed

Fix 22 bugs: SMTC crashes, mixer leaks/races, seekbar freeze, settings leak, UIA stalls, OSD, startup#1109
frans15-2006 wants to merge 99 commits into
unchihugo:masterfrom
frans15-2006:master

Conversation

@frans15-2006

Copy link
Copy Markdown
Contributor

Summary

Implements 22 previously unfiled bugs found via code-level review (not yet reported as GitHub issues). One commit per fix (24 commits — bug #22 ships as four scoped commits). No open issues are referenced; every change is scoped to a specific root cause found in the code.

Media flyout (SMTC)

  • Null session crashUpdateUI guard is now mediaSession?.ControlSession == null, so the "No media playing" reset runs instead of NRE-ing when app filtering removes the last session.
  • Dead-session COM crashes — added TryGetPlaybackInfo / TryGetTimelineProperties helpers and converted every raw GetPlaybackInfo() / GetTimelineProperties() call site; a session dying mid-event now logs instead of killing the process.
  • Seekbar freeze — the slider now captures the mouse for the drag and ends it on LostMouseCapture, so releasing outside the slider can no longer leave _isDragging stuck true.
  • Back button — gated on IsPreviousEnabled (was reusing IsNextEnabled), matching the taskbar widget.
  • Next Up popup — the auto-close continuation is aborted via the Closed event when the window is closed early, instead of animating a dead window inside async void.
  • Packaged players — "Open player" launches shell:AppsFolder\<AUMID> when the cached process id is -1, instead of throwing inside Process.GetProcessById.

Volume mixer / audio

  • MMDevice leaks — every re-attach path now disposes the superseded MMDevice.
  • Dead-session writes — volume/mute writes wrap the WASAPI calls in try/catch and keep the stale value instead of throwing COMException out of a WPF binding setter.
  • Zero-volume ↔ mute decoupling — mute no longer auto-triggers at 0 volume; it stays an independent toggle (matches native mixer behavior).

Taskbar widget

  • Secondary taskbars — fixed a StringBuilder.Equals(string) reference-comparison bug with a proper OrdinalIgnoreCase string compare.
  • UIA stalls — removed blocking .Wait() calls (up to 1.5s) on the UI dispatcher during taskbar element lookup; converted to async with timeouts.

Visualizer

  • Premultiplied alpha — bar edge pixels are premultiplied before writing to BGRA32, fixing bright fringes on antialiased edges.
  • Bar-count clamp — deserialized values clamped to 1–20 before resize (prevented a division crash).
  • Stop/restart race — snapshotting the capture instance instead of double-reading a field being swapped concurrently.
  • Atomic resize — replacement array is sized and published before BarCount changes, avoiding an out-of-bounds window.

Settings / API / OSD / startup

  • SettingsWindow leak — the SettingsManager.PropertyChanged handler is now unsubscribed on close.
  • Shutdown save — pending debounced settings save is flushed on exit.
  • Update client — timeout rotation raised to 3, client swap no longer disposes an in-flight client, User-Agent moved to a per-request header.
  • OSD hide — candidates are validated against the volume OSD's actual screen position so other shell islands can't be hidden by mistake.
  • Empty monitor list — flyout animations bail out and schedule a refresh instead of stranding the window off-screen.
  • Shutdown disposal — audio device monitor and toast activator are properly disposed/unregistered on exit.
  • Run key / lock-key sizing / logs path / purchase dialogs — null-safety and existence checks to prevent crashes and misleading error states.

Verification

No .NET SDK available in the authoring environment; verification was review-based (brace balance, no unguarded raw SMTC calls, no blocking UI-thread waits, re-read surrounding logic for each fix). CI (dotnet-format/build) passed on this branch. Manual smoke test before merge still recommended.

frans15-2006 and others added 30 commits August 4, 2026 08:48
- Subscribe to AudioEndpointVolume.OnVolumeNotification in VolumeMixerViewModel.AttachDevice (unsubscribe on reattach/dispose) so external volume-key changes push MasterVolume/IsMasterMuted immediately instead of relying on stale polling
- Add _suppressDevicePush guard to stop Sync->setter->device write-back loop that could overwrite OS changes with stale reads
- Make SyncMasterFromDevice dispatcher-aware and exception-safe (fixes cross-thread PropertyChanged from low-level hook)
- Marshal VolumeMixerWindow.ShowFlyout to UI dispatcher in MainWindow.HookCallback (hook fires off-UI-thread, before OS applies step)

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…resume

Visualizer:
- Stop WASAPI cleanly on Suspend and clear cached device ID; on Resume wait 2.5s for audio stack then restart with backoff
- Extend restart retries 5x500ms -> 10x800ms plus one delayed 15s follow-up so slow resume without further system events still recovers
- Re-arm single-shot silence watchdog while silence is short (was firing once then going blind) and null-guard DataAvailable timer access
- Restart on abnormal RecordingStopped (device invalidated underneath us)

Volume mixer (same S3 root cause: stale MMDevice, no DefaultDeviceChanged on desktop):
- Subscribe to PowerModeChanged.Resume + SessionUnlock/Logon and re-resolve default render device after 2s settle, fixing frozen volume flyout and single-session mixer after sleep

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Manifest:
- Add desktop/com to IgnorableNamespaces (strict parsers reject unknown unmarked extension namespaces -> 'error in parsing the app package')
- Fix Dependencies versions (bogus MaxVersionTested 10.0.0.0, stale 14393 min) to match wapproj 19041/26100

Installer:
- Check for .NET 10 Desktop Runtime (x64) in FluentFlyout_Installer.bat; GitHub builds are framework-dependent so a missing runtime installs fine but the app silently never starts (no window, no Task Manager entry) - offer the download instead of failing silently
- Document the prerequisite in README.txt and README.md msixbundle section
- Drop stale dev-machine AppInstallerUri from wapproj

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ng change

UpdateUi set the new single-copy text but left the previous song's
forever-loop TranslateTransform running until the async position pass
rebuilt marquees. Frames in between rendered the new text at the old
offset (empty widget), then snapped back (blink) - worst with loop
mode, which doubles the text.

- ResetMarquee helper stops the animation, zeroes X and restores
  single-copy text synchronously on song change and on hide
- Refresh cached StringWidth measurements + UpdateMarquees immediately
  for text changes only (play/pause updates skip it so scrolling never
  restarts); extracted shared RefreshCachedTextWidths for CalculateSize

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Alt+Tab/keys dying over time (regression vs v2.10, worse at boot):
HookCallback ran ShowMediaFlyout synchronously on the low-level keyboard
hook - blocking Dispatcher.Invoke, media COM fetches and animation setup
on every key press. Slow hooks stall all keystrokes system-wide and
Windows silently drops them. Debounce + queue via Dispatcher.BeginInvoke
so the hook returns immediately (volume path already deferred).

Dismiss jump-up-then-down:
CloseAnimation derived From from GetWindowPlacement (zeros for transient
handles) scaled by the selected monitor's DPI (wrong when the flyout
lives on another monitor). Now From comes from the window's actual
rendered position (PointToScreen + host monitor DPI, placement fallback),
To is always recomputed as From +/-20dip (pinned to From when animations
are off so stale storyboard values can't teleport the window).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… silent guards)

- OpenAnimation DIP scaling can race the window's DPI flip on mixed-DPI
  multi-monitor setups, stranding the flyout off-screen; queue a raw-pixel
  resting-position correction after the flight (no-op when already exact).
  Shared by media + volume flyouts.
- Normalize out-of-range Position setting to bottom-center instead of
  flying with a stale storyboard target.
- Log ShowMediaFlyout suppressions (null session/disabled/fullscreen) and
  every show with monitor + raw coords - these paths were silent, leaving
  empty logs for flyout-never-appears reports.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…D hunt)

- HideVolumeOsd enumerated XAML islands with NULL child-after, which always
  returns the FIRST match: infinite 100%-CPU spin + hiding the wrong
  island whenever it missed criteria. Chain properly through islands and
  their content bridges.
- Both flyout auto-hide loops (async void) caught only TaskCanceledException:
  any other throw was an abnormal exit with no trace. Catch Exception, log,
  emergency-hide. Per-session poll guarded so one dead session can't break
  the mixer refresh.
- AudioSessionModel: suppress device write-back while syncing from device
  (same echo guard as master volume).
- Breadcrumb logs on volume flyout show/hide for the next crash report.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Explorer recreates the OSD XAML island (new HWND), so the stored hidden
handle is dead and ShowFlyout's Zero-gate never re-hides. On
TaskbarCreated recovery (post-stabilization), reset the handle and
re-hide with retries, gated on VolumeControlEnabled.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…it audio

OnDataAvailable assumed 16-bit int or 32-bit float and treated interleaved
channels as mono samples: 24-bit streams (typical of spatial/Atmos
pipelines) decoded as permanent silence, and 6/8-channel streams fed the
FFT at multiples of the real rate. Decode per WaveFormat (8/16/24/32-int,
32-float via Encoding) and downmix each frame to mono, with a non-finite
guard. Stereo behavior is equivalent (L/R average vs alternating).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Process.MainModule throws Access Denied for admin-level processes seen
from a non-elevated caller, so sessions fell back to 'Unknown' with no
icon. Resolve exe paths via OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION)
+ QueryFullProcessImageName (granted cross-integrity), then read
FileVersionInfo/icons from the file itself: new MediaPlayerData.TryGetProcessPath
shared by the mixer icon lookup and the session display-name fallback chain
(FileDescription -> exe name -> window title/ProcessName). Process handles
now disposed.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…tion change

- Handle WM_DISPLAYCHANGE (was ignored): immediately drop cached tray/XAML
  handles, poisoned automation lookups and monitor id, then re-resolve the
  taskbar/position instead of running up to 1.5s stale. WindowProc is now an
  instance method to reach instance state.
- Invalid DPI no longer keeps the stale hit-test region: reset to empty
  (invisible + click-through) instead of leaving a ghost that eats clicks.
- Sanitize region rects (NaN/infinity/overflow/non-positive) to Empty so a
  garbage rect from transient geometry can never swallow taskbar input.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…exclusive mode)

pauseOtherMediaSessionsIfNeeded ran on every media-property change, so
thumbnail refreshes/progress updates re-paused the other app even when
playback focus never moved. Gate the metadata path on genuine
new-track/status boundaries (state transitions still pause via
CurrentSession_OnPlaybackStateChanged). Harden PauseOtherSessions fan-out
(null session guard + per-session catch; it is fire-and-forget).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Any duplicate launch signals the running instance to open its settings
window, so duplicate autostart entries/boot storms surface a window on
every login. Gate the signal: when the first instance started <30s ago,
the duplicate exits silently. Interactive re-launches keep opening settings.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
SongImage ImageBrush used Stretch=UniformToFill inside the fixed 78x78
frame, center-cropping rectangular covers. Use Uniform so the full artwork
is always visible (letterboxed).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Low-level keyboard callbacks run on the installing thread: the hook was
installed in the MainWindow ctor, so every keystroke waited behind UI-thread
stalls (thumbnail decode, dominant colors, COM) while the mouse stayed
smooth and no CPU spiked. Install the hook on a dedicated thread with its
own message pump (GetMessage loop + WM_QUIT shutdown, 3s bounded join);
marshal the LockWindow presentation step to the Dispatcher since window
creation/resource reads are UI-thread affine.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ntflyout

# Conflicts:
#	FluentFlyoutWPF/MainWindow.xaml.cs
#	FluentFlyoutWPF/ViewModels/VolumeMixerViewModel.cs

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Commit 08b24cb appended lines to MainWindow.xaml.cs while the file ended
without a trailing newline, leaving an orphaned
'ShowMediaFlyout(toggleMode: true);' statement outside the class - a
syntax error that broke the dotnet-format check (parse failure +
whitespace fix at EOF). Restore the clean file tail (matching master,
no final newline per .editorconfig insert_final_newline = false).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- The nullable warning at MainWindow.xaml.cs(1174,44) was the last
  dotnet-format failure: the FindResource(...).ToString() branch of the
  conditional expression is nullable-annotated, so assigning it to the
  non-nullable 'label' tripped CS8600 and the style fixer rewrote the
  file. Compute the label via a nullable resource with a fallback to
  the resource key (behavior preserved: "Insert" still skips the
  lookup, missing resources no longer throw into the outer catch).
- Revert the temporary debug instrumentation in dotnet-format.yml.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Fix 15 upstream issues: flyouts, mixer, widget, hooks, startup
Fix 22 bugs: SMTC crashes, mixer leaks/races, seekbar freeze, settings leak, UIA stalls, OSD, startup
@github-actions github-actions Bot added MainWindow / Media Flyout Changes to MainWindow including the Media Flyout SettingsWindow Changes to SettingsWindow or settings pages not related to flyouts/widgets Next Up Flyout Changes to NextUpWindow.xaml or NextUpWindow.xaml.cs TaskbarWindow Changes to TaskbarWindow; the container for taskbar widgets Volume Flyout Changes to the Volume Flyout or Volume Mixer Taskbar Widget Changes to the Taskbar Media Widget labels Sep 6, 2026
frans15-2006 and others added 13 commits September 6, 2026 06:39
Back_Click fired TrySkipPreviousAsync without awaiting or guarding it.
The command runs on ControlSession, which TrySkipPreviousAsync does not
null-check and which throws COMException when the SMTC session dies
between the click and the call - so the click either failed silently
(the discarded Task kept the exception as an unobserved task exception,
no log at all) or, once awaited anywhere, escaped the async void
handler and exited the process (App only logs before crashing).

Same treatment as the TryGetPlaybackInfo/TryGetTimelineProperties
guards: null-guard ControlSession with the established pattern first,
then await the command inside try/catch, log via Logger, and leave the
UI state as-is.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
PlayPause_Click fired TryTogglePlayPauseAsync without awaiting or
guarding it. The command runs on ControlSession, which
TryTogglePlayPauseAsync does not null-check and which throws
COMException when the SMTC session dies between the click and the call
- so the click either failed silently (the discarded Task kept the
exception as an unobserved task exception, no log at all) or, once
awaited anywhere, escaped the async void handler and exited the process
(App only logs before crashing).

Same treatment as the TryGetPlaybackInfo/TryGetTimelineProperties
guards: null-guard ControlSession with the established pattern first,
then await the command inside try/catch, log via Logger, and leave the
UI state as-is.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Forward_Click fired TrySkipNextAsync without awaiting or guarding it.
The command runs on ControlSession, which TrySkipNextAsync does not
null-check and which throws COMException when the SMTC session dies
between the click and the call - so the click either failed silently
(the discarded Task kept the exception as an unobserved task exception,
no log at all) or, once awaited anywhere, escaped the async void
handler and exited the process (App only logs before crashing).

Same treatment as the TryGetPlaybackInfo/TryGetTimelineProperties
guards: null-guard ControlSession with the established pattern first,
then await the command inside try/catch, log via Logger, and leave the
UI state as-is.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Repeat_Click awaits TryChangeAutoRepeatModeAsync on ControlSession
inside an async void handler with no try/catch. A session that dies
between the click and the call rethrows COMException on the await
continuation, which propagates to the dispatcher as an unhandled
exception and exits the process (App only logs before crashing). This
is the same failure class already fixed for the reads via the
TryGetPlaybackInfo/TryGetTimelineProperties guards; the write path was
missed.

Wrap the whole handler body in try/catch (GetActiveMediaSession's
focused-session lookup can also throw), log via Logger, and leave the
UI as-is: the optimistic SymbolRepeat flip above re-syncs from
AutoRepeatMode on the next playback-info update.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Shuffle_Click awaits TryChangeShuffleActiveAsync on ControlSession
inside an async void handler with no try/catch. A session that dies
between the click and the call rethrows COMException on the await
continuation, which propagates to the dispatcher as an unhandled
exception and exits the process (App only logs before crashing). This
is the same failure class already fixed for the reads via the
TryGetPlaybackInfo/TryGetTimelineProperties guards; the write path was
missed.

Wrap the whole handler body in try/catch (GetActiveMediaSession's
focused-session lookup can also throw), log via Logger, and leave the
UI as-is: the optimistic SymbolShuffle flip above re-syncs from
IsShuffleActive on the next playback-info update.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
## Summary
Fixes an unguarded crash path in the media flyout's control buttons — a session dying between the click and the WinRT call could throw unhandled inside an `async void` handler and kill the process. Same failure class already fixed for the SMTC read paths in unchihugo#1109 (`TryGetPlaybackInfo`/`TryGetTimelineProperties`), but these five click handlers were missed.

Directly addresses part of open issue unchihugo#807 ("clicking widget buttons crashes the app" / dead-session control calls).

## What changed
- `Back_Click` / `PlayPause_Click` / `Forward_Click` — added the file's existing `GetActiveMediaSession() is not { ControlSession: not null }` guard, wrapped the `Try*Async()` call in try/catch, logged failures instead of crashing.
- `Repeat_Click` / `Shuffle_Click` — same treatment; these were the actual process-killers since `App` has no `DispatcherUnhandledException` handler and a `COMException` here rethrows onto the dispatcher.

UI state (repeat/shuffle icon) isn't manually reverted on failure — it re-syncs from `AutoRepeatMode`/`IsShuffleActive` on the next playback-info update in `UpdateUI`, so no extra state-tracking was needed.

## Scope
Only `FluentFlyoutWPF/MainWindow.xaml.cs`, only these five handlers. One commit per handler (no shared helper — Repeat/Shuffle's failure surface differs from Back/PlayPause/Forward).

## Known related gaps (not touched, follow-up candidates)
- `TaskbarWidgetControl.xaml.cs` (~761–779): `Previous_Click`/`PlayPause_Click`/`Next_Click` call the same unguarded `Try*Async()` pattern in `async void` — this is likely the actual crash site in unchihugo#807 (widget buttons, not flyout buttons).
- `Seekbar_OnPreviewMouseLeftButtonUp` (~1882): unguarded `await ... TryChangePlaybackPositionAsync(...)` in `async void`.

## Verification
No .NET SDK available in the authoring environment. Review-based: brace/paren/bracket balance verified across the diff, each handler confirmed defined exactly once with the guarded call, no use-after-catch on pattern variables, no race window between the guard and the awaited call.
…ugo#807)

The taskbar widget buttons call TrySkipPreviousAsync / TryTogglePlayPauseAsync /
TrySkipNextAsync. Those helpers only null-checked the MediaSession wrapper, not
ControlSession, and did not catch COMException from a session that dies between
the check and the WinRT call. Because the widget handlers are async void, that
exception exited the process — the remaining crash site of unchihugo#807 after the
flyout-side click handlers were already guarded.

Null-check ControlSession, wrap each call in try/catch, log and return false.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
TaskbarWidgetControl.Previous_Click / PlayPause_Click / Next_Click are async
void and called the shared Try* helpers without a local catch. Even with the
helpers now guarded, a null MainWindow race (taskbar window recreated mid-click)
or any unexpected throw still exits the process via the dispatcher. Wrap each
handler (and the open-player context menu) in try/catch and log failures.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Seekbar_OnPreviewMouseLeftButtonUp is async void and awaited
TryChangePlaybackPositionAsync on session.ControlSession without null-checking
ControlSession or catching COMException. A session dying mid-drag (or a null
ControlSession) threw unhandled onto the dispatcher and killed the process; a
failed seek could also leave _isDragging stuck true so the position stopped
updating.

Null-check ControlSession, wrap the seek in try/catch, and clear _isDragging
in finally so the drag always ends.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
, unchihugo#923)

The taskbar visualizer captures WASAPI loopback, so it reacts to every render
stream — system sounds, blocked apps, and any non-music audio. TaskbarVisualizerHasContent
was set true whenever the FFT had energy, ignoring the app filter the media
widget already uses. That left the bars visible for blocked apps (unchihugo#923) and for
any audio that is not an SMTC music session (unchihugo#359).

Before marking content present, require GetActiveMediaSession() (which already
honours the blocked/allowed list) to report a Playing session. Otherwise force
HasContent false so the visualizer stays collapsed.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Some players (ytmdesktop2, certain UWP SMTC bridges) publish a valid session
with an empty Title, leaving the media flyout and taskbar widget blank. Add
ResolveDisplayTitle that returns the SMTC title when present and otherwise the
resolved process/app display name (then the session id).

Apply it on every path that paints title text (UpdateTaskbar, playback-state
updates, media-property updates, UpdateUI). Narrow the blank-interim suppress
from unchihugo#961 so it only kicks in once a non-blank title is already cached for the
session — first-time empty titles still fall through to the process-name
fallback.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
PauseOtherSessions called ControlSession.GetPlaybackInfo() raw inside a
fire-and-forget fan-out. A session dying between enumeration and the call
threw COMException (caught, but noisy) and skipped the safer TryGetPlaybackInfo
path already used everywhere else for the same failure class.

Route through TryGetPlaybackInfo and bind ControlSession once so TryPauseAsync
can't NRE on a null session.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…unchihugo#516)

Use Album Art as Accent Color only set ControlPlayPause.Background. The
AccentedButton style template repainted hover/pressed with the system accent
blue, so the button snapped off-theme on hover (unchihugo#910). The seekbar never
received the accent at all (unchihugo#516).

Switch the play/pause button to TransparentButton (so Background is respected),
paint it via ApplyAccentBrush, and dim a derived hover brush on MouseEnter/
Leave. Set Seekbar.Foreground so the filled track uses the same accent.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@Minemetero

Copy link
Copy Markdown

Vibe coded? :<

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read and agree to the FluentFlyout CLA


1 out of 2 committers have signed the CLA.
✅ (frans15-2006)[https://github.com/frans15-2006]
@frans15-2006
Frans15-2006 seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@frans15-2006

Copy link
Copy Markdown
Contributor Author

I have read and agree to the FluentFlyout CLA

github-actions Bot added a commit that referenced this pull request Sep 8, 2026
@frans15-2006

Copy link
Copy Markdown
Contributor Author

recheck

@github-actions github-actions Bot locked and limited conversation to collaborators Sep 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

MainWindow / Media Flyout Changes to MainWindow including the Media Flyout Next Up Flyout Changes to NextUpWindow.xaml or NextUpWindow.xaml.cs SettingsWindow Changes to SettingsWindow or settings pages not related to flyouts/widgets Taskbar Widget Changes to the Taskbar Media Widget TaskbarWindow Changes to TaskbarWindow; the container for taskbar widgets Volume Flyout Changes to the Volume Flyout or Volume Mixer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants