On a phone the Back button left the page under an open menu, sheet or dialog. An open overlay now says so (new IDOverlayHost, cascaded by MainLayout; OverlayService keeps them newest last): DModal and DDropdown through the cascade, so the D components stay free of app services, and the nav menu, PhoneSheet and the full-screen globe through the service. MainLayout's location-changing handler lets Back close the newest overlay instead of leaving the page; a link followed or the app's own navigation (signing out after its question, say) closes them all and goes on. Blazor can't tell Back from the app's navigation, so a capture-phase popstate listener in main.js marks Back (AppStatusService.TookBack). No history entries are pushed. Phone flow: Back closes the menu, a card's More sheet, the composer and the full-screen globe one after another without leaving the feed, and with nothing open goes back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
48 lines
1.4 KiB
Plaintext
48 lines
1.4 KiB
Plaintext
@inherits LayoutComponentBase
|
|
@implements IDisposable
|
|
|
|
@* The page and its menu. The overlays it holds (dialogs, menus, sheets: IDOverlayHost, cascaded) close with the phone's
|
|
Back button: while one is open, Back closes the newest instead of leaving the page; a link followed or the app's own
|
|
navigation closes them all and goes on. *@
|
|
<CascadingValue Value="(IDOverlayHost)Overlays" IsFixed="true">
|
|
<div class="relative flex flex-col md:flex-row w-full h-full">
|
|
<NavMenu />
|
|
|
|
<div class="block flex-1 relative w-full h-full">
|
|
<div class="block absolute overflow-y-auto w-full h-full p-3 md:py-4 md:pl-2 md:pr-4">
|
|
@Body
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ToastHost />
|
|
<PublicNoticeHost />
|
|
<ConfirmHost />
|
|
</CascadingValue>
|
|
|
|
@code {
|
|
[Inject] OverlayService Overlays { get; set; }
|
|
[Inject] NavigationManager Navigation { get; set; }
|
|
[Inject] AppStatusService Status { get; set; }
|
|
|
|
IDisposable changing;
|
|
|
|
protected override void OnInitialized() => changing = Navigation.RegisterLocationChangingHandler(OnLocationChanging);
|
|
|
|
async ValueTask OnLocationChanging(LocationChangingContext context)
|
|
{
|
|
var back = !context.IsNavigationIntercepted && Status.TookBack();
|
|
if (!Overlays.HasOpen)
|
|
return;
|
|
if (back)
|
|
{
|
|
context.PreventNavigation();
|
|
await Overlays.CloseTop(context.CancellationToken);
|
|
return;
|
|
}
|
|
await Overlays.CloseAll(context.CancellationToken);
|
|
}
|
|
|
|
public void Dispose() => changing?.Dispose();
|
|
}
|