From 3a3d692a5839473d1cb8023bfe37f33fee1d6cdd Mon Sep 17 00:00:00 2001 From: torvalds Date: Fri, 3 Jul 2026 12:51:19 +0700 Subject: [PATCH] =?UTF-8?q?fix(=D0=BA=D0=BB=D0=B0=D0=B2=D0=B0):=20=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D0=B2=D0=B8=D0=B0=D1=82=D1=83=D1=80=D0=B0=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D1=80=D1=8B=D0=B2=D0=B0=D0=BB=D0=B0=D1=81=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BA=D0=B0=D0=B6=D0=B4=D1=8B=D0=B9=20=D1=87?= =?UTF-8?q?=D0=B8=D1=85,=20=D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=20=D0=B7?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=D0=BC=20=D0=B0=20=D0=B3=D0=BB=D0=B0=D0=B2?= =?UTF-8?q?=D0=BD=D0=BE=D0=B5=20=D0=BD=D0=B0=D1=85=D1=83=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/frontend/screens/chats/chat_screen.dart | 14 ++++++++++- .../widgets/message_actions_overlay.dart | 25 +++++++++++++------ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/frontend/screens/chats/chat_screen.dart b/lib/frontend/screens/chats/chat_screen.dart index b8c4a81..0a8fd78 100644 --- a/lib/frontend/screens/chats/chat_screen.dart +++ b/lib/frontend/screens/chats/chat_screen.dart @@ -204,6 +204,7 @@ class _ChatScreenState extends State final TextEditingController _messageController = TextEditingController(); final FocusNode _messageFocusNode = FocusNode(); double _keyboardReserve = 0; + bool _keyboardWasOpen = false; final ScrollController _scrollController = ScrollController(); final GlobalKey _listKey = GlobalKey(); final ValueNotifier _hasText = ValueNotifier(false); @@ -841,6 +842,17 @@ class _ChatScreenState extends State super.didChangeAppLifecycleState(state); } + @override + void didChangeMetrics() { + super.didChangeMetrics(); + final view = View.of(context); + final keyboardOpen = view.viewInsets.bottom / view.devicePixelRatio > 100; + if (_keyboardWasOpen && !keyboardOpen && _messageFocusNode.hasFocus) { + _messageFocusNode.unfocus(); + } + _keyboardWasOpen = keyboardOpen; + } + @override void dispose() { _persistSessionCache(); @@ -4945,8 +4957,8 @@ class _ChatScreenState extends State final hadKeyboard = keyboard > 0; if (hadKeyboard) { setState(() => _keyboardReserve = keyboard); - FocusManager.instance.primaryFocus?.unfocus(); } + FocusManager.instance.primaryFocus?.unfocus(); await showAttachmentSheet( context, title: widget.name, diff --git a/lib/frontend/widgets/message_actions_overlay.dart b/lib/frontend/widgets/message_actions_overlay.dart index 1c04519..46fe066 100644 --- a/lib/frontend/widgets/message_actions_overlay.dart +++ b/lib/frontend/widgets/message_actions_overlay.dart @@ -229,8 +229,9 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> final n = _actions.length; const reach = _radius + _btnSize / 2; final padding = MediaQuery.paddingOf(context); + final keyboardInset = MediaQuery.viewInsetsOf(context).bottom; final topMargin = padding.top + _hMargin; - final bottomMargin = padding.bottom + _hMargin; + final bottomMargin = math.max(padding.bottom, keyboardInset) + _hMargin; final rect = widget.originRect; final spaceBelow = screenSize.height - bottomMargin - (rect.bottom + 16); @@ -330,25 +331,29 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> const itemHeight = 42.0; const vPad = 6.0; final menuHeight = n * itemHeight + vPad * 2; + final keyboardInset = MediaQuery.viewInsetsOf(context).bottom; + final bottomLimit = screenSize.height - keyboardInset; + final maxMenuY = math.max(8.0, bottomLimit - menuHeight - 8.0); late double menuX; late double menuY; if (widget.interaction != MessageActionsInteraction.dragAndRelease) { - final spaceBelow = screenSize.height - widget.tapPoint.dy - 8; + final spaceBelow = bottomLimit - widget.tapPoint.dy - 8; _showBelow = spaceBelow >= menuHeight || widget.tapPoint.dy < menuHeight; final rawY = _showBelow ? widget.tapPoint.dy : widget.tapPoint.dy - menuHeight; - menuY = rawY.clamp(8.0, screenSize.height - menuHeight - 8.0).toDouble(); + menuY = rawY.clamp(8.0, maxMenuY).toDouble(); menuX = widget.tapPoint.dx .clamp(8.0, screenSize.width - menuWidth - 8.0) .toDouble(); } else { - final spaceBelow = screenSize.height - widget.originRect.bottom - 24; + final spaceBelow = bottomLimit - widget.originRect.bottom - 24; final spaceAbove = widget.originRect.top - 24; _showBelow = spaceBelow >= menuHeight || spaceBelow >= spaceAbove; - menuY = _showBelow + final rawY = _showBelow ? widget.originRect.bottom + 10 : widget.originRect.top - 10 - menuHeight; + menuY = rawY.clamp(8.0, maxMenuY).toDouble(); final rawX = widget.isMe ? widget.originRect.right - menuWidth : widget.originRect.left; @@ -636,9 +641,10 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> ? widget.originRect.bottom + 10 : widget.originRect.top - 10; } + final bottomLimit = size.height - MediaQuery.viewInsetsOf(context).bottom; left = left.clamp(8.0, size.width - menuWidth - 8.0); - top = top.clamp(8.0, size.height - 160.0); - final maxHeight = math.min(size.height * 0.6, size.height - top - 8.0); + top = top.clamp(8.0, math.max(8.0, bottomLimit - 160.0)); + final maxHeight = math.min(size.height * 0.6, bottomLimit - top - 8.0); return Positioned( left: left, @@ -929,7 +935,10 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> Widget _buildLabelBanner(Size size, double t) { final label = _hoveredIndex == -1 ? null : _actions[_hoveredIndex].label; - final bottomInset = MediaQuery.paddingOf(context).bottom; + final bottomInset = math.max( + MediaQuery.paddingOf(context).bottom, + MediaQuery.viewInsetsOf(context).bottom, + ); return Positioned( left: 0, right: 0,