11using System . Collections . Specialized ;
22using Avalonia ;
3+ using Avalonia . Automation ;
34using Avalonia . Collections ;
45using Avalonia . Controls ;
56using Avalonia . Controls . ApplicationLifetimes ;
@@ -50,6 +51,12 @@ public partial class MainWindowViewModel : ViewModelBase
5051 public event EventHandler < bool > ? CanGoBackChanged ;
5152 public event EventHandler < PageType > ? CurrentPageChanged ;
5253
54+ [ ObservableProperty ]
55+ private string _announcementText = "" ;
56+
57+ [ ObservableProperty ]
58+ private AutomationLiveSetting _announcementLiveSetting = AutomationLiveSetting . Polite ;
59+
5360 // ─── Operations panel ─────────────────────────────────────────────────────
5461 public AvaloniaList < OperationViewModel > Operations => AvaloniaOperationRegistry . OperationViewModels ;
5562
@@ -113,6 +120,8 @@ private void OnPageViewModelPropertyChanged(object? sender, System.ComponentMode
113120
114121 public MainWindowViewModel ( )
115122 {
123+ AccessibilityAnnouncementService . AnnouncementRequested += OnAnnouncementRequested ;
124+
116125 DiscoverPage = new DiscoverSoftwarePage ( ) ;
117126 UpdatesPage = new SoftwareUpdatesPage ( ) ;
118127 InstalledPage = new InstalledPackagesPage ( ) ;
@@ -203,6 +212,15 @@ public MainWindowViewModel()
203212 LoadDefaultPage ( ) ;
204213 }
205214
215+ private void OnAnnouncementRequested ( object ? _ , AccessibilityAnnouncement announcement )
216+ {
217+ AnnouncementLiveSetting = announcement . LiveSetting ;
218+ AnnouncementText = string . Empty ;
219+ Dispatcher . UIThread . Post (
220+ ( ) => AnnouncementText = announcement . Message ,
221+ DispatcherPriority . Background ) ;
222+ }
223+
206224 // ─── Navigation ──────────────────────────────────────────────────────────
207225 public void LoadDefaultPage ( )
208226 {
@@ -265,9 +283,14 @@ public void NavigateTo(PageType newPage_t, bool toHistory = true)
265283 if ( newPage_t is PageType . About ) { _ = ShowAboutDialog ( ) ; return ; }
266284 if ( newPage_t is PageType . Quit ) { ( Application . Current ? . ApplicationLifetime as IClassicDesktopStyleApplicationLifetime ) ? . Shutdown ( ) ; return ; }
267285
268- Sidebar . SelectNavButtonForPage ( newPage_t ) ;
286+ if ( _currentPage == newPage_t )
287+ {
288+ // Re-focus the primary control even when we're already on the page
289+ ( CurrentPageContent as AbstractPackagesPage ) ? . FocusPackageList ( ) ;
290+ return ;
291+ }
269292
270- if ( _currentPage == newPage_t ) return ;
293+ Sidebar . SelectNavButtonForPage ( newPage_t ) ;
271294
272295 var newPage = GetPageForType ( newPage_t ) ;
273296 var oldPage = CurrentPageContent as Control ;
@@ -286,7 +309,6 @@ public void NavigateTo(PageType newPage_t, bool toHistory = true)
286309 CanGoBackChanged ? . Invoke ( this , true ) ;
287310 }
288311
289- ( newPage as AbstractPackagesPage ) ? . FocusPackageList ( ) ;
290312 ( newPage as AbstractPackagesPage ) ? . FilterPackages ( ) ;
291313 ( newPage as IEnterLeaveListener ) ? . OnEnter ( ) ;
292314
@@ -305,9 +327,29 @@ public void NavigateTo(PageType newPage_t, bool toHistory = true)
305327 GlobalSearchEnabled = false ;
306328 }
307329
330+ // Focus after search state is restored so MegaQueryVisible is already correct
331+ ( newPage as AbstractPackagesPage ) ? . FocusPackageList ( ) ;
332+
333+ AccessibilityAnnouncementService . Announce ( GetPageAnnouncement ( newPage_t ) ) ;
308334 CurrentPageChanged ? . Invoke ( this , newPage_t ) ;
309335 }
310336
337+ private static string GetPageAnnouncement ( PageType pageType ) => pageType switch
338+ {
339+ PageType . Discover => CoreTools . Translate ( "Discover Packages" ) ,
340+ PageType . Updates => CoreTools . Translate ( "Software Updates" ) ,
341+ PageType . Installed => CoreTools . Translate ( "Installed Packages" ) ,
342+ PageType . Bundles => CoreTools . Translate ( "Package Bundles" ) ,
343+ PageType . Settings => CoreTools . Translate ( "Settings" ) ,
344+ PageType . Managers => CoreTools . Translate ( "Package Managers" ) ,
345+ PageType . OwnLog => CoreTools . Translate ( "UniGetUI Log" ) ,
346+ PageType . ManagerLog => CoreTools . Translate ( "Package Manager logs" ) ,
347+ PageType . OperationHistory => CoreTools . Translate ( "Operation history" ) ,
348+ PageType . Help => CoreTools . Translate ( "Help" ) ,
349+ PageType . ReleaseNotes => CoreTools . Translate ( "Release notes" ) ,
350+ _ => CoreTools . Translate ( "UniGetUI" ) ,
351+ } ;
352+
311353 public void NavigateBack ( )
312354 {
313355 if ( CurrentPageContent is IInnerNavigationPage navPage && navPage . CanGoBack ( ) )
0 commit comments