diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index 0a54cb4..78dfdf2 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -309,9 +309,7 @@ class _ChannelChatScreenState extends State { navigator.pop(); navigator.pushReplacement( buildQuickSwitchRoute( - index == 0 - ? const ContactsScreen(hideBackButton: true) - : const MapScreen(hideBackButton: true), + index == 0 ? const ContactsScreen() : const MapScreen(), ), ); } diff --git a/lib/screens/channels_screen.dart b/lib/screens/channels_screen.dart index 3268e1c..2b4584a 100644 --- a/lib/screens/channels_screen.dart +++ b/lib/screens/channels_screen.dart @@ -35,9 +35,7 @@ import 'map_screen.dart'; import 'settings_screen.dart'; class ChannelsScreen extends StatefulWidget { - final bool hideBackButton; - - const ChannelsScreen({super.key, this.hideBackButton = false}); + const ChannelsScreen({super.key}); @override State createState() => _ChannelsScreenState(); @@ -110,7 +108,11 @@ class _ChannelsScreenState extends State context, MaterialPageRoute(builder: (context) => const SettingsScreen()), ), - appBar: AppBar( + appBarBuilder: (context, pinned) => AppBar( + // Top-level tab: no auto back-arrow. Hamburger when the panel is not + // pinned; nothing when it is (panel is docked), so no dead arrow (#390). + automaticallyImplyLeading: false, + leading: pinned ? null : AppShell.drawerMenuButton(), title: AppBarTitle(context.l10n.channels_title), centerTitle: true, bottom: const SyncProgressAppBarBottom(), @@ -570,13 +572,13 @@ class _ChannelsScreenState extends State case 0: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const ContactsScreen(hideBackButton: true)), + buildQuickSwitchRoute(const ContactsScreen()), ); break; case 2: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const MapScreen(hideBackButton: true)), + buildQuickSwitchRoute(const MapScreen()), ); break; } diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index 9ffbae6..d9ad000 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -48,9 +48,7 @@ enum RoomLoginDestination { chat, management } enum ContactOperationType { import, export, zeroHopShare } class ContactsScreen extends StatefulWidget { - final bool hideBackButton; - - const ContactsScreen({super.key, this.hideBackButton = false}); + const ContactsScreen({super.key}); @override State createState() => _ContactsScreenState(); @@ -329,7 +327,11 @@ class _ContactsScreenState extends State context, MaterialPageRoute(builder: (context) => const SettingsScreen()), ), - appBar: AppBar( + appBarBuilder: (context, pinned) => AppBar( + // Top-level tab: no auto back-arrow. Hamburger when the panel is not + // pinned; nothing when it is (panel is docked), so no dead arrow (#390). + automaticallyImplyLeading: false, + leading: pinned ? null : AppShell.drawerMenuButton(), title: AppBarTitle(context.l10n.contacts_title), bottom: const SyncProgressAppBarBottom(), actions: [ @@ -949,13 +951,13 @@ class _ContactsScreenState extends State case 1: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const ChannelsScreen(hideBackButton: true)), + buildQuickSwitchRoute(const ChannelsScreen()), ); break; case 2: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const MapScreen(hideBackButton: true)), + buildQuickSwitchRoute(const MapScreen()), ); break; } diff --git a/lib/screens/line_of_sight_map_screen.dart b/lib/screens/line_of_sight_map_screen.dart index 2e83150..49e35f5 100644 --- a/lib/screens/line_of_sight_map_screen.dart +++ b/lib/screens/line_of_sight_map_screen.dart @@ -1362,13 +1362,13 @@ class _LineOfSightMapScreenState extends State { case 0: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const ContactsScreen(hideBackButton: true)), + buildQuickSwitchRoute(const ContactsScreen()), ); break; case 1: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const ChannelsScreen(hideBackButton: true)), + buildQuickSwitchRoute(const ChannelsScreen()), ); break; } diff --git a/lib/screens/map_screen.dart b/lib/screens/map_screen.dart index 2b9ade1..7c5752d 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -42,7 +42,6 @@ class MapScreen extends StatefulWidget { final String? highlightLabel; final String? highlightMarkerKey; final double highlightZoom; - final bool hideBackButton; const MapScreen({ super.key, @@ -50,7 +49,6 @@ class MapScreen extends StatefulWidget { this.highlightLabel, this.highlightMarkerKey, this.highlightZoom = 15.0, - this.hideBackButton = false, }); @override @@ -421,7 +419,12 @@ class _MapScreenState extends State { context, MaterialPageRoute(builder: (context) => const SettingsScreen()), ), - appBar: AppBar( + appBarBuilder: (context, pinned) => AppBar( + // Top-level tab: no auto back-arrow. Hamburger when the panel is + // not pinned; nothing when pinned (panel docked), so no dead + // arrow (#390). + automaticallyImplyLeading: false, + leading: pinned ? null : AppShell.drawerMenuButton(), title: AppBarTitle(context.l10n.map_title), centerTitle: true, bottom: const SyncProgressAppBarBottom(), @@ -1636,13 +1639,13 @@ class _MapScreenState extends State { case 0: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const ContactsScreen(hideBackButton: true)), + buildQuickSwitchRoute(const ContactsScreen()), ); break; case 1: Navigator.pushReplacement( context, - buildQuickSwitchRoute(const ChannelsScreen(hideBackButton: true)), + buildQuickSwitchRoute(const ChannelsScreen()), ); break; } diff --git a/lib/widgets/app_shell.dart b/lib/widgets/app_shell.dart index 106255f..1225393 100644 --- a/lib/widgets/app_shell.dart +++ b/lib/widgets/app_shell.dart @@ -89,6 +89,20 @@ class AppShell extends StatefulWidget { return AppShellBackAction.background; } + /// Hamburger for a top-level tab's app-bar leading, used when the nav panel + /// is NOT pinned (transient drawer). Top-level tabs must set + /// `automaticallyImplyLeading: false` and use this instead, so the pinned + /// desktop layout shows no leading at all rather than a dead back-arrow that + /// only backgrounds (a no-op on desktop): the #390 eyesore. A [Builder] so + /// `openDrawer` resolves a context beneath the Scaffold. + static Widget drawerMenuButton() => Builder( + builder: (context) => IconButton( + icon: const Icon(Icons.menu), + tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip, + onPressed: () => Scaffold.of(context).openDrawer(), + ), + ); + @override State createState() => _AppShellState(); }