角色会话长按说话向上取消录音

This commit is contained in:
mh 2025-11-06 11:50:29 +08:00
parent 04b2131efc
commit 8b1727fcaa
3 changed files with 86 additions and 9 deletions

View File

@ -28,6 +28,7 @@ class IMVoiceHoldView: UIView {
var audioDuration: Int = 0
var counting: Int = 0
private var isRecording: Bool = false
private var isInCancelArea: Bool = false //
public var audioPathUrl: URL?
var recordFinishedAction: ((_ url: URL?) -> Void)?
@ -129,7 +130,8 @@ class IMVoiceHoldView: UIView {
stackView.spacing = 5.0
stackView.distribution = .fill
stackView.alignment = .fill
insertSubview(stackView, belowSubview: overlayBg)
// insertSubview(stackView, belowSubview: overlayBg)
insertSubview(stackView, aboveSubview: overlayBg)
stackView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.bottom.equalTo(voiceIconDecorationView.snp.top).offset(-15)
@ -155,6 +157,23 @@ class IMVoiceHoldView: UIView {
private func setupData() {
recordTool = AudioRecordTool()
}
// MARK: -
func updateCancelState(isInCancelArea: Bool) {
guard self.isInCancelArea != isInCancelArea else { return }
self.isInCancelArea = isInCancelArea
if isInCancelArea {
//
voiceIconDecorationView.image = UIImage(named: "role_chat_voice_cancel")
tipLabel.text = "Release to cancel"
} else {
// 退
voiceIconDecorationView.image = UIImage(named: "role_chat_voice_normal")
tipLabel.text = "Release to send"
}
}
private func setupEvent() {
recordTool.timerChangedBlock = { [weak self] counting in
@ -178,32 +197,59 @@ class IMVoiceHoldView: UIView {
isRecording = on
if on {
//
isInCancelArea = false
voiceIconDecorationView.image = UIImage(named: "role_chat_voice_normal")
tipLabel.text = "Release to send"
wave.play()
recordTool.startRecord { [weak self] audioURL in
self?.audioPathUrl = audioURL
dlog("🎤audioURL: \(String(describing: audioURL))")
if let count = self?.counting, count < 10{
Hud.toast(str: "语音时间太短")
return
guard let self = self else { return }
//
//
if !self.isInCancelArea {
if self.counting < 10 {
Hud.toast(str: "语音时间太短")
return
}
self.recordFinishedAction?(audioURL)
} else {
//
dlog("☁️🎤录音已取消(在取消区域)")
}
self?.recordFinishedAction?(audioURL)
}
} else {
wave.stop()
stopRecord()
//
if isInCancelArea {
cancelRecord()
} else {
stopRecord()
}
}
}
// MARK: - Functions
func stopRecord() {
// startRecord
recordTool.stopRecord()
// if counting < 10{
// Hud.toast(str: "")
// return
// }
}
func cancelRecord() {
//
//
recordTool.stopRecord()
audioPathUrl = nil
dlog("☁️🎤录音已取消")
}
// MARK: - Other

View File

@ -14,6 +14,8 @@ protocol SessionInputOperateViewDelegate: AnyObject {
func operateTapMoreAction()
func operateTapHelpAction()
func operateTapInputFieldAction()
//
func operateVoiceDragAction(location: CGPoint)
}
enum InputOperateState {
@ -223,7 +225,7 @@ class SessionInputOperateView: UIView {
//
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
longPress.minimumPressDuration = 0.2 // 0.5
longPress.minimumPressDuration = 0.2 // 0.2
voiceHoldView.addGestureRecognizer(longPress)
$state.sink { [weak self] state in
@ -311,7 +313,8 @@ class SessionInputOperateView: UIView {
case .began:
delegate?.operateVoiceAction(on: true)
case .changed:
break
// voiceIconDecorationView
handleDragGesture(gesture)
case .ended:
delegate?.operateVoiceAction(on: false)
case .cancelled, .failed:
@ -320,6 +323,15 @@ class SessionInputOperateView: UIView {
break
}
}
private func handleDragGesture(_ gesture: UILongPressGestureRecognizer) {
// window
guard let window = self.window else { return }
let location = gesture.location(in: window)
// delegate
delegate?.operateVoiceDragAction(location: location)
}
}
extension SessionInputOperateView: UITextFieldDelegate {

View File

@ -255,6 +255,25 @@ extension SessionController: SessionInputOperateViewDelegate{
voiceHoldView.record(on: on)
}
func operateVoiceDragAction(location: CGPoint) {
// voiceHoldView
voiceHoldView.layoutIfNeeded()
// window voiceHoldView
let locationInVoiceHoldView = voiceHoldView.convert(location, from: nil)
// voiceIconDecorationView voiceHoldView frame
// voiceIconDecorationView voiceHoldView frame voiceHoldView
let decorationViewFrame = voiceHoldView.voiceIconDecorationView.frame
// voiceIconDecorationView
// y decorationView
let isInCancelArea = locationInVoiceHoldView.y < decorationViewFrame.origin.y
//
voiceHoldView.updateCancelState(isInCancelArea: isInCancelArea)
}
func operateTapMoreAction() {
view.endEditing(true)