diff --git a/ios/Podfile.lock b/ios/Podfile.lock deleted file mode 100644 index 0351d891af..0000000000 --- a/ios/Podfile.lock +++ /dev/null @@ -1,249 +0,0 @@ -PODS: - - app_settings (5.1.1): - - Flutter - - device_info_plus (0.0.1): - - Flutter - - DKImagePickerController/Core (4.3.9): - - DKImagePickerController/ImageDataManager - - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.9) - - DKImagePickerController/PhotoGallery (4.3.9): - - DKImagePickerController/Core - - DKPhotoGallery - - DKImagePickerController/Resource (4.3.9) - - DKPhotoGallery (0.0.19): - - DKPhotoGallery/Core (= 0.0.19) - - DKPhotoGallery/Model (= 0.0.19) - - DKPhotoGallery/Preview (= 0.0.19) - - DKPhotoGallery/Resource (= 0.0.19) - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Core (0.0.19): - - DKPhotoGallery/Model - - DKPhotoGallery/Preview - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Model (0.0.19): - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Preview (0.0.19): - - DKPhotoGallery/Model - - DKPhotoGallery/Resource - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Resource (0.0.19): - - SDWebImage - - SwiftyGif - - file_picker (0.0.1): - - DKImagePickerController/PhotoGallery - - Flutter - - Firebase/CoreOnly (10.29.0): - - FirebaseCore (= 10.29.0) - - Firebase/Messaging (10.29.0): - - Firebase/CoreOnly - - FirebaseMessaging (~> 10.29.0) - - firebase_core (3.3.0): - - Firebase/CoreOnly (= 10.29.0) - - Flutter - - firebase_messaging (15.0.4): - - Firebase/Messaging (= 10.29.0) - - firebase_core - - Flutter - - FirebaseCore (10.29.0): - - FirebaseCoreInternal (~> 10.0) - - GoogleUtilities/Environment (~> 7.12) - - GoogleUtilities/Logger (~> 7.12) - - FirebaseCoreInternal (10.29.0): - - "GoogleUtilities/NSData+zlib (~> 7.8)" - - FirebaseInstallations (10.29.0): - - FirebaseCore (~> 10.0) - - GoogleUtilities/Environment (~> 7.8) - - GoogleUtilities/UserDefaults (~> 7.8) - - PromisesObjC (~> 2.1) - - FirebaseMessaging (10.29.0): - - FirebaseCore (~> 10.0) - - FirebaseInstallations (~> 10.0) - - GoogleDataTransport (~> 9.3) - - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - - GoogleUtilities/Environment (~> 7.8) - - GoogleUtilities/Reachability (~> 7.8) - - GoogleUtilities/UserDefaults (~> 7.8) - - nanopb (< 2.30911.0, >= 2.30908.0) - - Flutter (1.0.0) - - GoogleDataTransport (9.4.1): - - GoogleUtilities/Environment (~> 7.7) - - nanopb (< 2.30911.0, >= 2.30908.0) - - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/AppDelegateSwizzler (7.13.3): - - GoogleUtilities/Environment - - GoogleUtilities/Logger - - GoogleUtilities/Network - - GoogleUtilities/Privacy - - GoogleUtilities/Environment (7.13.3): - - GoogleUtilities/Privacy - - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.13.3): - - GoogleUtilities/Environment - - GoogleUtilities/Privacy - - GoogleUtilities/Network (7.13.3): - - GoogleUtilities/Logger - - "GoogleUtilities/NSData+zlib" - - GoogleUtilities/Privacy - - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.13.3)": - - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (7.13.3) - - GoogleUtilities/Reachability (7.13.3): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (7.13.3): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - image_picker_ios (0.0.1): - - Flutter - - integration_test (0.0.1): - - Flutter - - nanopb (2.30910.0): - - nanopb/decode (= 2.30910.0) - - nanopb/encode (= 2.30910.0) - - nanopb/decode (2.30910.0) - - nanopb/encode (2.30910.0) - - package_info_plus (0.4.5): - - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - PromisesObjC (2.4.0) - - SDWebImage (5.20.0): - - SDWebImage/Core (= 5.20.0) - - SDWebImage/Core (5.20.0) - - share_plus (0.0.1): - - Flutter - - sqlite3 (3.47.1): - - sqlite3/common (= 3.47.1) - - sqlite3/common (3.47.1) - - sqlite3/dbstatvtab (3.47.1): - - sqlite3/common - - sqlite3/fts5 (3.47.1): - - sqlite3/common - - sqlite3/perf-threadsafe (3.47.1): - - sqlite3/common - - sqlite3/rtree (3.47.1): - - sqlite3/common - - sqlite3_flutter_libs (0.0.1): - - Flutter - - FlutterMacOS - - sqlite3 (~> 3.47.1) - - sqlite3/dbstatvtab - - sqlite3/fts5 - - sqlite3/perf-threadsafe - - sqlite3/rtree - - SwiftyGif (5.4.5) - - url_launcher_ios (0.0.1): - - Flutter - - video_player_avfoundation (0.0.1): - - Flutter - - FlutterMacOS - - wakelock_plus (0.0.1): - - Flutter - -DEPENDENCIES: - - app_settings (from `.symlinks/plugins/app_settings/ios`) - - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - - file_picker (from `.symlinks/plugins/file_picker/ios`) - - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - - Flutter (from `Flutter`) - - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - integration_test (from `.symlinks/plugins/integration_test/ios`) - - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - - share_plus (from `.symlinks/plugins/share_plus/ios`) - - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) - - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) - -SPEC REPOS: - trunk: - - DKImagePickerController - - DKPhotoGallery - - Firebase - - FirebaseCore - - FirebaseCoreInternal - - FirebaseInstallations - - FirebaseMessaging - - GoogleDataTransport - - GoogleUtilities - - nanopb - - PromisesObjC - - SDWebImage - - sqlite3 - - SwiftyGif - -EXTERNAL SOURCES: - app_settings: - :path: ".symlinks/plugins/app_settings/ios" - device_info_plus: - :path: ".symlinks/plugins/device_info_plus/ios" - file_picker: - :path: ".symlinks/plugins/file_picker/ios" - firebase_core: - :path: ".symlinks/plugins/firebase_core/ios" - firebase_messaging: - :path: ".symlinks/plugins/firebase_messaging/ios" - Flutter: - :path: Flutter - image_picker_ios: - :path: ".symlinks/plugins/image_picker_ios/ios" - integration_test: - :path: ".symlinks/plugins/integration_test/ios" - package_info_plus: - :path: ".symlinks/plugins/package_info_plus/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" - share_plus: - :path: ".symlinks/plugins/share_plus/ios" - sqlite3_flutter_libs: - :path: ".symlinks/plugins/sqlite3_flutter_libs/darwin" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - video_player_avfoundation: - :path: ".symlinks/plugins/video_player_avfoundation/darwin" - wakelock_plus: - :path: ".symlinks/plugins/wakelock_plus/ios" - -SPEC CHECKSUMS: - app_settings: 017320c6a680cdc94c799949d95b84cb69389ebc - device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d - DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c - DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 - Firebase: cec914dab6fd7b1bd8ab56ea07ce4e03dd251c2d - firebase_core: 57aeb91680e5d5e6df6b888064be7c785f146efb - firebase_messaging: c862b3d2b973ecc769194dc8de09bd22c77ae757 - FirebaseCore: 30e9c1cbe3d38f5f5e75f48bfcea87d7c358ec16 - FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 - FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd - FirebaseMessaging: 7b5d8033e183ab59eb5b852a53201559e976d366 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a - GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 - image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 - integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 - nanopb: 438bc412db1928dac798aa6fd75726007be04262 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8 - share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad - sqlite3: 1e522f0938463e44b7faf50393b40bdc1e1e456d - sqlite3_flutter_libs: 1b4e98da20ebd4e9b1240269b78cdcf492dbe9f3 - SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 - wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1 - -PODFILE CHECKSUM: 7ed5116924b3be7e8fb75f7aada61e057028f5c7 - -COCOAPODS: 1.16.2 diff --git a/lib/widgets/home.dart b/lib/widgets/home.dart index 45c5ea43c1..7b189d6eee 100644 --- a/lib/widgets/home.dart +++ b/lib/widgets/home.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; - import '../generated/l10n/zulip_localizations.dart'; import '../model/narrow.dart'; import 'action_sheet.dart'; @@ -21,27 +20,26 @@ import 'subscription_list.dart'; import 'text.dart'; import 'theme.dart'; -enum _HomePageTab { - inbox, - channels, - directMessages, -} +enum _HomePageTab { inbox, channels, directMessages } class HomePage extends StatefulWidget { const HomePage({super.key}); static Route buildRoute({required int accountId}) { - return MaterialAccountWidgetRoute(accountId: accountId, + return MaterialAccountWidgetRoute( + accountId: accountId, loadingPlaceholderPage: _LoadingPlaceholderPage(accountId: accountId), - page: const HomePage()); + page: const HomePage(), + ); } /// Navigate to [HomePage], ensuring that its route is at the root level. static void navigate(BuildContext context, {required int accountId}) { final navigator = Navigator.of(context); navigator.popUntil((route) => route.isFirst); - unawaited(navigator.pushReplacement( - HomePage.buildRoute(accountId: accountId))); + unawaited( + navigator.pushReplacement(HomePage.buildRoute(accountId: accountId)), + ); } @override @@ -71,7 +69,7 @@ class _HomePageState extends State { String get _currentTabTitle { final zulipLocalizations = ZulipLocalizations.of(context); - switch(_tab.value) { + switch (_tab.value) { case _HomePageTab.inbox: return zulipLocalizations.inboxPageTitle; case _HomePageTab.channels: @@ -84,40 +82,50 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { const pageBodies = [ - (_HomePageTab.inbox, InboxPageBody()), - (_HomePageTab.channels, SubscriptionListPageBody()), + (_HomePageTab.inbox, InboxPageBody()), + (_HomePageTab.channels, SubscriptionListPageBody()), // TODO(#1094): Users (_HomePageTab.directMessages, RecentDmConversationsPageBody()), ]; _NavigationBarButton button(_HomePageTab tab, IconData icon) { - return _NavigationBarButton(icon: icon, + return _NavigationBarButton( + icon: icon, selected: _tab.value == tab, onPressed: () { _tab.value = tab; - }); + }, + ); } // TODO(a11y): add tooltips for these buttons final navigationBarButtons = [ - button(_HomePageTab.inbox, ZulipIcons.inbox), - _NavigationBarButton( icon: ZulipIcons.message_feed, + button(_HomePageTab.inbox, ZulipIcons.inbox), + _NavigationBarButton( + icon: ZulipIcons.message_feed, selected: false, - onPressed: () => Navigator.push(context, - MessageListPage.buildRoute(context: context, - narrow: const CombinedFeedNarrow()))), - button(_HomePageTab.channels, ZulipIcons.hash_italic), + onPressed: + () => Navigator.push( + context, + MessageListPage.buildRoute( + context: context, + narrow: const CombinedFeedNarrow(), + ), + ), + ), + button(_HomePageTab.channels, ZulipIcons.hash_italic), // TODO(#1094): Users button(_HomePageTab.directMessages, ZulipIcons.user), - _NavigationBarButton( icon: ZulipIcons.menu, + _NavigationBarButton( + icon: ZulipIcons.menu, selected: false, - onPressed: () => _showMainMenu(context, tabNotifier: _tab)), + onPressed: () => _showMainMenu(context, tabNotifier: _tab), + ), ]; final designVariables = DesignVariables.of(context); return Scaffold( - appBar: ZulipAppBar(titleSpacing: 16, - title: Text(_currentTabTitle)), + appBar: ZulipAppBar(titleSpacing: 16, title: Text(_currentTabTitle)), body: Stack( children: [ for (final (tab, body) in pageBodies) @@ -125,13 +133,16 @@ class _HomePageState extends State { // [SemanticsProperties.namesRoute] to structure this UI better // for screen-reader software. Offstage(offstage: tab != _tab.value, child: body), - ]), + ], + ), bottomNavigationBar: DecoratedBox( decoration: BoxDecoration( border: Border(top: BorderSide(color: designVariables.borderBar)), - color: designVariables.bgBotBar), + color: designVariables.bgBotBar, + ), child: SafeArea( - child: SizedBox(height: 48, + child: SizedBox( + height: 48, child: Center( child: ConstrainedBox( // TODO(design): determine a suitable max width for bottom nav bar @@ -141,7 +152,14 @@ class _HomePageState extends State { children: [ for (final navigationBarButton in navigationBarButtons) Expanded(child: navigationBarButton), - ]))))))); + ], + ), + ), + ), + ), + ), + ), + ); } } @@ -153,7 +171,8 @@ class _LoadingPlaceholderPage extends StatefulWidget { final int accountId; @override - State<_LoadingPlaceholderPage> createState() => _LoadingPlaceholderPageState(); + State<_LoadingPlaceholderPage> createState() => + _LoadingPlaceholderPageState(); } class _LoadingPlaceholderPageState extends State<_LoadingPlaceholderPage> { @@ -179,8 +198,8 @@ class _LoadingPlaceholderPageState extends State<_LoadingPlaceholderPage> { @override Widget build(BuildContext context) { final zulipLocalizations = ZulipLocalizations.of(context); - final realmUrl = GlobalStoreWidget.of(context) - .getAccount(widget.accountId)!.realmUrl; + final realmUrl = + GlobalStoreWidget.of(context).getAccount(widget.accountId)!.realmUrl; return Scaffold( appBar: AppBar(), @@ -199,14 +218,30 @@ class _LoadingPlaceholderPageState extends State<_LoadingPlaceholderPage> { child: Column( children: [ const SizedBox(height: 16), - Text(zulipLocalizations.tryAnotherAccountMessage(realmUrl.toString())), + Text( + zulipLocalizations.tryAnotherAccountMessage( + realmUrl.toString(), + ), + ), const SizedBox(height: 8), ElevatedButton( - onPressed: () => Navigator.push(context, - MaterialWidgetRoute(page: const ChooseAccountPage())), - child: Text(zulipLocalizations.tryAnotherAccountButton)), - ]))), - ]))); + onPressed: + () => Navigator.push( + context, + MaterialWidgetRoute( + page: const ChooseAccountPage(), + ), + ), + child: Text(zulipLocalizations.tryAnotherAccountButton), + ), + ], + ), + ), + ), + ], + ), + ), + ); } } @@ -226,9 +261,9 @@ class _NavigationBarButton extends StatelessWidget { final designVariables = DesignVariables.of(context); final iconColor = WidgetStateColor.fromMap({ - WidgetState.pressed: designVariables.iconSelected, - ~WidgetState.pressed: selected ? designVariables.iconSelected - : designVariables.icon, + WidgetState.pressed: designVariables.iconSelected, + ~WidgetState.pressed: + selected ? designVariables.iconSelected : designVariables.icon, }); return AnimatedScaleOnTap( @@ -242,12 +277,16 @@ class _NavigationBarButton extends StatelessWidget { splashFactory: NoSplash.splashFactory, highlightColor: designVariables.navigationButtonBg, shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(4))), - ).copyWith(foregroundColor: iconColor))); + borderRadius: BorderRadius.all(Radius.circular(4)), + ), + ).copyWith(foregroundColor: iconColor), + ), + ); } } -void _showMainMenu(BuildContext context, { +void _showMainMenu( + BuildContext context, { required ValueNotifier<_HomePageTab> tabNotifier, }) { final menuItems = [ @@ -262,8 +301,7 @@ void _showMainMenu(BuildContext context, { _ChannelsButton(tabNotifier: tabNotifier), _DirectMessagesButton(tabNotifier: tabNotifier), // TODO(#1094): Users - const _MyProfileButton(), - const _SwitchAccountButton(), + const _CombinedProfileButton(), // TODO(#198): Set my status // const SizedBox(height: 8), // TODO(#97): Settings @@ -296,20 +334,34 @@ void _showMainMenu(BuildContext context, { crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.min, children: [ - Flexible(child: InsetShadowBox( - top: 8, bottom: 8, - color: designVariables.bgBotBar, - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), - child: Column(children: menuItems)))), + Flexible( + child: InsetShadowBox( + top: 8, + bottom: 8, + color: designVariables.bgBotBar, + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Column(children: menuItems), + ), + ), + ), const Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: AnimatedScaleOnTap( scaleEnd: 0.95, duration: Duration(milliseconds: 100), - child: ActionSheetCancelButton())), - ]))); - }); + child: ActionSheetCancelButton(), + ), + ), + ], + ), + ), + ); + }, + ); } abstract class _MenuButton extends StatelessWidget { @@ -329,8 +381,11 @@ abstract class _MenuButton extends StatelessWidget { Widget buildLeading(BuildContext context) { assert(icon != null); final designVariables = DesignVariables.of(context); - return Icon(icon, size: _iconSize, - color: selected ? designVariables.iconSelected : designVariables.icon); + return Icon( + icon, + size: _iconSize, + color: selected ? designVariables.iconSelected : designVariables.icon, + ); } void onPressed(BuildContext context); @@ -348,9 +403,11 @@ abstract class _MenuButton extends StatelessWidget { final designVariables = DesignVariables.of(context); final zulipLocalizations = ZulipLocalizations.of(context); - final borderSideSelected = BorderSide(width: 1, + final borderSideSelected = BorderSide( + width: 1, strokeAlign: BorderSide.strokeAlignOutside, - color: designVariables.borderMenuButtonSelected); + color: designVariables.borderMenuButtonSelected, + ); final buttonStyle = TextButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 8), foregroundColor: designVariables.labelMenuButton, @@ -362,16 +419,21 @@ abstract class _MenuButton extends StatelessWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ).copyWith( backgroundColor: WidgetStateColor.fromMap({ - WidgetState.hovered: designVariables.bgMenuButtonActive.withFadedAlpha(0.5), + WidgetState.hovered: designVariables.bgMenuButtonActive.withFadedAlpha( + 0.5, + ), WidgetState.focused: designVariables.bgMenuButtonActive, WidgetState.pressed: designVariables.bgMenuButtonActive, WidgetState.any: - selected ? designVariables.bgMenuButtonSelected : Colors.transparent, + selected + ? designVariables.bgMenuButtonSelected + : Colors.transparent, }), side: WidgetStateBorderSide.fromMap({ WidgetState.pressed: null, ~WidgetState.pressed: selected ? borderSideSelected : null, - })); + }), + ); return AnimatedScaleOnTap( duration: const Duration(milliseconds: 100), @@ -381,15 +443,31 @@ abstract class _MenuButton extends StatelessWidget { child: TextButton( onPressed: () => _handlePress(context), style: buttonStyle, - child: Row(spacing: 8, children: [ - SizedBox.square(dimension: _iconSize, - child: buildLeading(context)), - Expanded(child: Text(label(zulipLocalizations), - // TODO(design): determine if we prefer to wrap - overflow: TextOverflow.ellipsis, - style: const TextStyle(fontSize: 19, height: 26 / 19) - .merge(weightVariableTextStyle(context, wght: selected ? 600 : 400)))), - ])))); + child: Row( + spacing: 8, + children: [ + SizedBox.square( + dimension: _iconSize, + child: buildLeading(context), + ), + Expanded( + child: Text( + label(zulipLocalizations), + // TODO(design): determine if we prefer to wrap + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 19, height: 26 / 19).merge( + weightVariableTextStyle( + context, + wght: selected ? 600 : 400, + ), + ), + ), + ), + ], + ), + ), + ), + ); } } @@ -438,8 +516,12 @@ class _MentionsButton extends _MenuButton { @override void onPressed(BuildContext context) { - Navigator.of(context).push(MessageListPage.buildRoute( - context: context, narrow: const MentionsNarrow())); + Navigator.of(context).push( + MessageListPage.buildRoute( + context: context, + narrow: const MentionsNarrow(), + ), + ); } } @@ -456,8 +538,12 @@ class _StarredMessagesButton extends _MenuButton { @override void onPressed(BuildContext context) { - Navigator.of(context).push(MessageListPage.buildRoute( - context: context, narrow: const StarredMessagesNarrow())); + Navigator.of(context).push( + MessageListPage.buildRoute( + context: context, + narrow: const StarredMessagesNarrow(), + ), + ); } } @@ -474,8 +560,12 @@ class _CombinedFeedButton extends _MenuButton { @override void onPressed(BuildContext context) { - Navigator.of(context).push(MessageListPage.buildRoute( - context: context, narrow: const CombinedFeedNarrow())); + Navigator.of(context).push( + MessageListPage.buildRoute( + context: context, + narrow: const CombinedFeedNarrow(), + ), + ); } } @@ -509,50 +599,58 @@ class _DirectMessagesButton extends _NavigationBarMenuButton { _HomePageTab get navigationTarget => _HomePageTab.directMessages; } -class _MyProfileButton extends _MenuButton { - const _MyProfileButton(); - - @override - IconData? get icon => null; - - @override - Widget buildLeading(BuildContext context) { - final store = PerAccountStoreWidget.of(context); - return Avatar( - userId: store.selfUserId, size: _MenuButton._iconSize, borderRadius: 4); - } - - @override - String label(ZulipLocalizations zulipLocalizations) { - return zulipLocalizations.mainMenuMyProfile; - } +class _CombinedProfileButton extends StatelessWidget { + const _CombinedProfileButton(); @override - void onPressed(BuildContext context) { + Widget build(BuildContext context) { final store = PerAccountStoreWidget.of(context); - Navigator.of(context).push( - ProfilePage.buildRoute(context: context, userId: store.selfUserId)); - } -} - -class _SwitchAccountButton extends _MenuButton { - const _SwitchAccountButton(); - - @override - // TODO(design): choose an icon - IconData? get icon => null; - - @override - Widget buildLeading(BuildContext context) => const SizedBox.shrink(); - - @override - String label(ZulipLocalizations zulipLocalizations) { - return zulipLocalizations.switchAccountButton; - } - - @override - void onPressed(BuildContext context) { - Navigator.of(context).push(MaterialWidgetRoute(page: const ChooseAccountPage())); + final designVariables = DesignVariables.of(context); + const iconSize = 30.0; + + return InkWell( + onTap: () { + Navigator.of(context).push( + ProfilePage.buildRoute(context: context, userId: store.selfUserId), + ); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + children: [ + // Avatar section + Avatar( + userId: store.selfUserId, + size: _MenuButton._iconSize, + borderRadius: 4, + ), + const SizedBox(width: 12), + + // Profile text + Expanded( + child: Text( + ZulipLocalizations.of(context).mainMenuMyProfile, + style: Theme.of(context).textTheme.bodyLarge, + ), + ), + + // Switch account icon button + IconButton( + icon: Icon( + Icons.compare_arrows_rounded, + color: designVariables.icon, + size: iconSize, + ), + onPressed: () { + Navigator.of( + context, + ).push(MaterialWidgetRoute(page: const ChooseAccountPage())); + }, + ), + ], + ), + ), + ); } } @@ -591,13 +689,15 @@ class _AnimatedScaleOnTapState extends State { Widget build(BuildContext context) { return GestureDetector( behavior: HitTestBehavior.translucent, - onTapDown: (_) => _changeScale(widget.scaleEnd), - onTapUp: (_) => _changeScale(1), + onTapDown: (_) => _changeScale(widget.scaleEnd), + onTapUp: (_) => _changeScale(1), onTapCancel: () => _changeScale(1), child: AnimatedScale( scale: _scale, duration: widget.duration, curve: Curves.easeOut, - child: widget.child)); + child: widget.child, + ), + ); } }