diff --git a/Rosetta/Features/Chats/ChatDetail/MessageVoiceView.swift b/Rosetta/Features/Chats/ChatDetail/MessageVoiceView.swift index c755690..659e43c 100644 --- a/Rosetta/Features/Chats/ChatDetail/MessageVoiceView.swift +++ b/Rosetta/Features/Chats/ChatDetail/MessageVoiceView.swift @@ -23,6 +23,10 @@ final class MessageVoiceView: UIView { private var totalDuration: TimeInterval = 0 // original duration for label reset /// Center of play button in this view's coordinate space (for external blob positioning). var playButtonCenter: CGPoint { playButton.center } + /// Whether the waveform is accepting scrub gestures (true during playback). + var isScrubbingEnabled: Bool { waveformView.enableScrubbing } + /// Frame of the waveform in this view's coordinate space. + var waveformFrame: CGRect { waveformView.frame } // MARK: - Layout Constants (Telegram exact: ChatMessageInteractiveFileNode) diff --git a/Rosetta/Features/Chats/ChatDetail/NativeMessageCell.swift b/Rosetta/Features/Chats/ChatDetail/NativeMessageCell.swift index ef9ba50..e83ad49 100644 --- a/Rosetta/Features/Chats/ChatDetail/NativeMessageCell.swift +++ b/Rosetta/Features/Chats/ChatDetail/NativeMessageCell.swift @@ -319,7 +319,6 @@ final class NativeMessageCell: UICollectionViewCell { // Raster bubble image (Telegram-exact tail) — added last so it renders above outline bubbleImageView.contentMode = .scaleToFill bubbleView.addSubview(bubbleImageView) - bubbleView.clipsToBounds = true // clips voice blob animation to bubble bounds contentView.addSubview(bubbleView) // Text (CoreTextLabel — no font/color/lines config; all baked into CoreTextTextLayout) @@ -3088,6 +3087,15 @@ extension NativeMessageCell: UIGestureRecognizerDelegate { override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { guard let pan = gestureRecognizer as? UIPanGestureRecognizer else { return true } if isInSelectionMode { return false } // No swipe in selection mode + + // If touch is on the waveform during playback, let the waveform's scrub gesture win + if !voiceView.isHidden, voiceView.isScrubbingEnabled { + let pointInVoice = pan.location(in: voiceView) + if voiceView.waveformFrame.contains(pointInVoice) { + return false + } + } + let velocity = pan.velocity(in: contentView) // Telegram: only left swipe (negative velocity.x), clear horizontal dominance return velocity.x < 0 && abs(velocity.x) > abs(velocity.y) * 2.0