Skip to content

Fix: send button moves off screen when typing during a locked media recording - #2267

Open
yuriipopow wants to merge 1 commit into
TelegramMessenger:masterfrom
yuriipopow:bug-fix
Open

Fix: send button moves off screen when typing during a locked media recording#2267
yuriipopow wants to merge 1 commit into
TelegramMessenger:masterfrom
yuriipopow:bug-fix

Conversation

@yuriipopow

Copy link
Copy Markdown

Fix: send button moves off screen when typing during a locked media recording

Problem

Start recording a voice message in a chat and lock the recording, then press any key on the keyboard. The "send" button slides off the right edge of the screen, leaving no way to send the recording — the only remaining options are cancelling or deleting it.

This affects both voice messages and video messages — the input panel takes the same layout path for either.

Steps to reproduce

  1. Open any chat.
  2. Tap the text field so the software keyboard comes up.
  3. Press and hold the mic button, then swipe up to lock the recording.
  4. Press any character key.

The send button disappears past the right edge of the panel.

Repeat with the button switched to video mode (tap the mic button to toggle to the camera icon, then hold and swipe up to lock) — same result.

Screen recordings

Attaching screen recordings of the bug and of the behaviour after the fix.

Before — the bug:

output2.mp4

After — with the fix applied:

output.mp4

Root cause

While a media recording is in progress, the text field is not removed — it is only faded out (audioRecordingItemsAlpha = 0.0, applied to richTextInputNode in updateLayout). Nothing in ChatControllerMediaRecording.swift resigns first responder when recording starts or when lockMediaRecorder() runs, so the field stays focused and keeps receiving keystrokes. The typed character lands in the invisible field and flips inputHasText to true.

inputHasText drives the layout of the entire right-hand side of the input panel. In particular:

var mediaActionButtonsFrame = CGRect(origin: CGPoint(x: textInputContainerBackgroundFrame.maxX + 6.0, ...))
if inputHasText || self.extendedSearchLayout || hasMediaDraft || ... {
    mediaActionButtonsFrame.origin.x = width + 8.0
}

mediaActionButtons is the control that acts as "send" during a locked recording — the accessibility area labelled VoiceOver_MessageContextSend is positioned against mediaActionButtonsFrame. So the panel switches into its "there is text to send" layout and parks the recording control off screen, while separately scaling in the regular text-send button for text the user cannot see.

None of this is specific to audio: ChatTextInputPanelMediaRecordingState has both an .audio(recorder:isLocked:) and a .video(status:isLocked:) case, and the panel reads only whether mediaRecordingState is non-nil here. Video messages therefore hit exactly the same layout path and exhibit the same bug.

Fix

The recording layout must not depend on the content of a field that is invisible and unreachable during recording:

let inputHasText = !isRecording && !(self.richTextInputNode?.inputContentIsEmpty ?? true)

isRecording is already computed earlier in the same updateLayout call, and is set for any non-nil mediaRecordingState — so this covers voice and video messages alike, with no separate handling for either.

This single condition covers every dependent site consistently — updateActionButtons(hasText:), textFieldInsets.right, the mediaActionButtons position, and the sendActionButtons scale. During a recording the panel now lays out exactly as it does when the recording is started from an empty field. Typed text is not discarded: it reappears in the field once the recording ends.

Guarding only the mediaActionButtonsFrame assignment would not be enough — inputHasText also selects textFieldInsets.right, which feeds textInputContainerBackgroundFrame.maxX, and therefore the mic button's own origin. A narrower patch leaves the button on screen but misplaced.

Notes

This PR intentionally leaves the input behaviour alone. The text field keeps first responder while a recording is in progress, so the keyboard stays up and typed text is retained and reappears once the recording ends — that may well be deliberate, and it isn't mine to judge from the outside. Nothing here resigns focus, blocks editing, or dismisses the keyboard.

The change is confined to layout: it only stops the panel from moving the recording controls out of reach. Whatever the intended input behaviour is, it is preserved exactly as before.

Testing

Built debug_sim_arm64 and verified manually on iPhone 17 Pro (iOS 26.5), for both voice and video messages: with the fix, the send button stays in place while typing during a locked recording, and the text-send button no longer appears.

Changed files

  • submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift — one line, plus an explanatory comment.

@yuriipopow
yuriipopow marked this pull request as ready for review August 2, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant