From e905301080feb8f68467344af6b988da3627c841 Mon Sep 17 00:00:00 2001 From: senseiGai Date: Sat, 18 Apr 2026 11:42:11 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81:=20=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=B1=D0=B8=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B8=D0=B1?= =?UTF-8?q?=D1=80=D0=BE=D0=BE=D1=82=D0=B4=D0=B0=D1=87=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B8=20=D0=B3=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D1=81=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BE?= =?UTF-8?q?=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Хаптик срабатывает ДО запуска AVAudioSession (иначе глушится) - Убрана двойная вибрация (AudioServicesPlaySystemSound + impactOccurred) - Прогрев Taptic Engine в didMoveToWindow + beginTracking - Recording chrome показывается синхронно до async Task --- .../Chats/ChatDetail/ComposerView.swift | 17 ++--------------- .../Chats/ChatDetail/RecordingMicButton.swift | 13 ++++--------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/Rosetta/Features/Chats/ChatDetail/ComposerView.swift b/Rosetta/Features/Chats/ChatDetail/ComposerView.swift index 49fb58c..0f7a417 100644 --- a/Rosetta/Features/Chats/ChatDetail/ComposerView.swift +++ b/Rosetta/Features/Chats/ChatDetail/ComposerView.swift @@ -1,4 +1,3 @@ -import AudioToolbox import AVFAudio @preconcurrency import AVFoundation import Lottie @@ -1179,22 +1178,10 @@ extension ComposerView: RecordingMicButtonDelegate { isRecording = true isRecordingLocked = false setRecordingFlowState(.recordingUnlocked) + // Haptic is fired by RecordingMicButton.beginRecording() (prepared generator) + // BEFORE this delegate call — so it fires before AVAudioSession starts. presentRecordingChrome(locked: false, animatePanel: true) - // Haptic 100ms after chrome — overlay is at alpha ~0.7, visually present. - // Fired outside the Task so AVAudioSession can't suppress it, and - // button state guards can't skip it. - let hapticGenerator = UIImpactFeedbackGenerator(style: .medium) - hapticGenerator.prepare() - print("[HAPTIC] prepare() called, scheduling impactOccurred in 100ms") - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in - let isStillRecording = self?.isRecording == true - print("[HAPTIC] firing impactOccurred — isRecording=\(isStillRecording) flowState=\(String(describing: self?.recordingFlowState))") - hapticGenerator.impactOccurred() - AudioServicesPlaySystemSound(1519) - print("[HAPTIC] impactOccurred + SystemSound(1519) DONE") - } - recordingStartTask?.cancel() recordingStartTask = Task { @MainActor [weak self] in guard let self else { return } diff --git a/Rosetta/Features/Chats/ChatDetail/RecordingMicButton.swift b/Rosetta/Features/Chats/ChatDetail/RecordingMicButton.swift index 19fb45f..6d7ce75 100644 --- a/Rosetta/Features/Chats/ChatDetail/RecordingMicButton.swift +++ b/Rosetta/Features/Chats/ChatDetail/RecordingMicButton.swift @@ -1,4 +1,3 @@ -import AudioToolbox import QuartzCore import UIKit @@ -127,7 +126,6 @@ final class RecordingMicButton: UIControl { didLockHaptic = false impactFeedback.prepare() - print("[HAPTIC-MIC] beginTracking — prepare() called") recordingDelegate?.micButtonRecordingArmed(self) // Start hold timer — after 0.19s we begin recording @@ -257,14 +255,13 @@ final class RecordingMicButton: UIControl { // MARK: - State Transitions private func beginRecording() { - guard recordingState == .waiting else { - print("[HAPTIC-MIC] beginRecording SKIPPED — state=\(recordingState)") - return - } + guard recordingState == .waiting else { return } recordingState = .recording holdTimer = nil - print("[HAPTIC-MIC] beginRecording — calling delegate") + // Haptic fires BEFORE delegate — delegate starts AVAudioSession + // which suppresses Taptic Engine. + fireHaptic() startDisplayLink() recordingDelegate?.micButtonRecordingBegan(self) } @@ -343,9 +340,7 @@ final class RecordingMicButton: UIControl { /// UIFeedbackGenerator API and hits Taptic Engine directly. /// Telegram uses this as fallback in HapticFeedback.swift. private func fireHaptic() { - print("[HAPTIC-MIC] fireHaptic() — state=\(recordingState)") impactFeedback.impactOccurred() - AudioServicesPlaySystemSound(1519) impactFeedback.prepare() }