From 260348736d814ab2403ba7e7ed260b3e971fa7db Mon Sep 17 00:00:00 2001 From: Tommy Chow Date: Fri, 9 Jan 2026 01:47:02 -0500 Subject: [PATCH] fix landscape bottom padding in chat bottom bar --- lib/screens/channel/chat/chat.dart | 168 ++++++++++-------- .../channel/chat/widgets/chat_bottom_bar.dart | 26 ++- 2 files changed, 115 insertions(+), 79 deletions(-) diff --git a/lib/screens/channel/chat/chat.dart b/lib/screens/channel/chat/chat.dart index 18ec8e3e..99da7004 100644 --- a/lib/screens/channel/chat/chat.dart +++ b/lib/screens/channel/chat/chat.dart @@ -53,46 +53,58 @@ class Chat extends StatelessWidget { style: context.defaultTextStyle.copyWith( fontSize: chatStore.settings.fontSize, ), - child: FrostyScrollbar( - controller: chatStore.scrollController, - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top, - bottom: - chatStore.bottomBarHeight + - (chatStore.assetsStore.showEmoteMenu - ? 0 - : MediaQuery.of(context).padding.bottom), - ), - child: Observer( - builder: (context) { - return ListView.builder( - reverse: true, - padding: (listPadding ?? EdgeInsets.zero).add( - EdgeInsets.only( - bottom: - chatStore.bottomBarHeight + - (chatStore.assetsStore.showEmoteMenu - ? 0 - : MediaQuery.of( - context, - ).padding.bottom), - ), - ), - addAutomaticKeepAlives: false, - controller: chatStore.scrollController, - itemCount: chatStore.renderMessages.length, - itemBuilder: (context, index) => ChatMessage( - ircMessage: - chatStore.renderMessages[chatStore - .renderMessages - .length - - 1 - - index], - chatStore: chatStore, - ), - ); - }, - ), + child: Builder( + builder: (context) { + // Don't add bottom padding in horizontal landscape + // (immersive mode with home indicator on side). + // landscapeForceVerticalChat uses portrait layout + // with normal system UI, so still needs padding. + final isHorizontalLandscape = + context.isLandscape && + !chatStore.settings.landscapeForceVerticalChat; + final bottomPadding = + chatStore.assetsStore.showEmoteMenu || + isHorizontalLandscape + ? 0.0 + : MediaQuery.of(context).padding.bottom; + + return FrostyScrollbar( + controller: chatStore.scrollController, + padding: EdgeInsets.only( + top: MediaQuery.of(context).padding.top, + bottom: + chatStore.bottomBarHeight + bottomPadding, + ), + child: Observer( + builder: (context) { + return ListView.builder( + reverse: true, + padding: (listPadding ?? EdgeInsets.zero) + .add( + EdgeInsets.only( + bottom: + chatStore.bottomBarHeight + + bottomPadding, + ), + ), + addAutomaticKeepAlives: false, + controller: chatStore.scrollController, + itemCount: chatStore.renderMessages.length, + itemBuilder: (context, index) => + ChatMessage( + ircMessage: + chatStore.renderMessages[chatStore + .renderMessages + .length - + 1 - + index], + chatStore: chatStore, + ), + ); + }, + ), + ); + }, ), ), ), @@ -119,41 +131,51 @@ class Chat extends StatelessWidget { onAddChat: onAddChat, ), ), - AnimatedPadding( - duration: const Duration(milliseconds: 200), - padding: EdgeInsets.only( - left: 4, - top: 4, - right: 4, - bottom: - chatStore.bottomBarHeight + - (chatStore.assetsStore.showEmoteMenu - ? 0 - : MediaQuery.of(context).padding.bottom), - ), - child: Observer( - builder: (_) => AnimatedSwitcher( + Builder( + builder: (context) { + final isHorizontalLandscape = + context.isLandscape && + !chatStore.settings.landscapeForceVerticalChat; + return AnimatedPadding( duration: const Duration(milliseconds: 200), - switchInCurve: Curves.easeOut, - switchOutCurve: Curves.easeIn, - child: chatStore.autoScroll - ? null - : ElevatedButton.icon( - onPressed: chatStore.resumeScroll, - icon: const Icon(Icons.arrow_downward_rounded), - label: Text( - chatStore.messageBuffer.isNotEmpty - ? '${chatStore.messageBuffer.length} new ${chatStore.messageBuffer.length == 1 ? 'message' : 'messages'}' - : 'Resume scroll', - style: const TextStyle( - fontFeatures: [ - FontFeature.tabularFigures(), - ], + padding: EdgeInsets.only( + left: 4, + top: 4, + right: 4, + bottom: + chatStore.bottomBarHeight + + (chatStore.assetsStore.showEmoteMenu || + isHorizontalLandscape + ? 0 + : MediaQuery.of(context).padding.bottom), + ), + child: Observer( + builder: (_) => AnimatedSwitcher( + duration: const Duration(milliseconds: 200), + switchInCurve: Curves.easeOut, + switchOutCurve: Curves.easeIn, + child: chatStore.autoScroll + ? null + : ElevatedButton.icon( + onPressed: chatStore.resumeScroll, + icon: const Icon( + Icons.arrow_downward_rounded, + ), + label: Text( + chatStore.messageBuffer.isNotEmpty + ? '${chatStore.messageBuffer.length} new ${chatStore.messageBuffer.length == 1 ? 'message' : 'messages'}' + : 'Resume scroll', + style: const TextStyle( + fontFeatures: [ + FontFeature.tabularFigures(), + ], + ), + ), ), - ), - ), - ), - ), + ), + ), + ); + }, ), ], ), diff --git a/lib/screens/channel/chat/widgets/chat_bottom_bar.dart b/lib/screens/channel/chat/widgets/chat_bottom_bar.dart index 5061aa47..de1a7c2b 100644 --- a/lib/screens/channel/chat/widgets/chat_bottom_bar.dart +++ b/lib/screens/channel/chat/widgets/chat_bottom_bar.dart @@ -367,21 +367,35 @@ class ChatBottomBar extends StatelessWidget { ], ); + // Don't add bottom padding when: + // - Emote menu is open: The emote menu provides its own bottom boundary + // - In horizontal landscape mode: System is in immersive mode and home + // indicator is on the side (left/right), not the content bottom. + // SafeArea handles left/right insets for the notch. + // Note: landscapeForceVerticalChat uses portrait layout in landscape + // orientation with normal (non-immersive) system UI, so it still needs + // bottom padding. + final isHorizontalLandscape = + context.isLandscape && + !chatStore.settings.landscapeForceVerticalChat; + final needsBottomPadding = + !chatStore.assetsStore.showEmoteMenu && !isHorizontalLandscape; + return isFullscreenOverlay ? Padding( padding: EdgeInsets.only( - bottom: chatStore.assetsStore.showEmoteMenu - ? 0 - : MediaQuery.of(context).padding.bottom, + bottom: needsBottomPadding + ? MediaQuery.of(context).padding.bottom + : 0, ), child: bottomBarContent, ) : BlurredContainer( gradientDirection: GradientDirection.down, padding: EdgeInsets.only( - bottom: chatStore.assetsStore.showEmoteMenu - ? 0 - : MediaQuery.of(context).padding.bottom, + bottom: needsBottomPadding + ? MediaQuery.of(context).padding.bottom + : 0, ), child: bottomBarContent, );