diff --git a/src/MauiSherpa.LinuxGtk/LinuxToolbarManager.cs b/src/MauiSherpa.LinuxGtk/LinuxToolbarManager.cs index 7865307..6d68654 100644 --- a/src/MauiSherpa.LinuxGtk/LinuxToolbarManager.cs +++ b/src/MauiSherpa.LinuxGtk/LinuxToolbarManager.cs @@ -121,12 +121,24 @@ public void AttachToWindow(Gtk.Window window) _copilotButton.OnClicked += (s, _) => _copilotContext.ToggleOverlay(); _headerBar.PackStart(_copilotButton); - // Settings gear button on the right side + // Settings gear button beside copilot var settingsButton = Gtk.Button.New(); settingsButton.SetIconName("emblem-system-symbolic"); settingsButton.SetTooltipText("Settings"); settingsButton.OnClicked += (s, _) => OpenSettingsDialog(); - _headerBar.PackEnd(settingsButton); + _headerBar.PackStart(settingsButton); + + // Doctor button beside settings + var doctorButton = Gtk.Button.New(); + var doctorIconName = _themeService.IsDarkMode ? "fa-stethoscope-white-24.png" : "fa-stethoscope-24.png"; + var doctorIconPath = System.IO.Path.Combine(AppContext.BaseDirectory, "Resources", doctorIconName); + if (System.IO.File.Exists(doctorIconPath)) + doctorButton.SetChild(Gtk.Image.NewFromFile(doctorIconPath)); + else + doctorButton.SetIconName("dialog-information-symbolic"); + doctorButton.SetTooltipText("Doctor"); + doctorButton.OnClicked += (s, _) => _toolbarService.RequestNavigation("/doctor"); + _headerBar.PackStart(doctorButton); _window.SetTitlebar(_headerBar); } diff --git a/src/MauiSherpa/Components/MainLayout.razor b/src/MauiSherpa/Components/MainLayout.razor index a0dfafa..62f45db 100644 --- a/src/MauiSherpa/Components/MainLayout.razor +++ b/src/MauiSherpa/Components/MainLayout.razor @@ -158,8 +158,7 @@ protected override void OnInitialized() { ThemeService.ThemeChanged += OnThemeChanged; - if (PlatformInfo.IsWindows) - ToolbarService.NavigationRequested += OnNavigationRequested; + ToolbarService.NavigationRequested += OnNavigationRequested; } protected override void OnAfterRender(bool firstRender) @@ -265,8 +264,7 @@ { ThemeService.ThemeChanged -= OnThemeChanged; NavManager.LocationChanged -= OnLocationChanged; - if (PlatformInfo.IsWindows) - ToolbarService.NavigationRequested -= OnNavigationRequested; + ToolbarService.NavigationRequested -= OnNavigationRequested; } private void OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e) @@ -277,12 +275,25 @@ ToolbarService.NotifyRouteChanged(route); } + private void OpenCopilot() => CopilotContext.OpenOverlay(); + private void OnNavigationRequested(string route) { - InvokeAsync(() => NavManager.NavigateTo(route)); - } + // Defensively validate/normalize the route coming from native UI + if (string.IsNullOrWhiteSpace(route)) + { + return; + } - private void OpenCopilot() => CopilotContext.OpenOverlay(); + route = route.Trim(); + + // Reject absolute URIs/schemes to avoid accidental external navigation + if (Uri.TryCreate(route, UriKind.Absolute, out _)) + { + return; + } + _ = InvokeAsync(() => NavManager.NavigateTo(route)); + } }