137 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Swift
		
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Swift
		
	
	
	
| //
 | |
| //  SpeechManager.swift
 | |
| //  Crush
 | |
| //
 | |
| //  Created by Leon on 2025/8/1.
 | |
| //
 | |
| 
 | |
| import Foundation
 | |
| 
 | |
| class SpeechManager {
 | |
|     // MARK: - Properties
 | |
|     static let shared = SpeechManager()
 | |
|     private weak var currentModel: SpeechModel?
 | |
|     private var timer: TimerModel?
 | |
|     private var timerCount: Int = 0
 | |
|     
 | |
|     private init() {}
 | |
|     
 | |
|     // MARK: - Private Methods
 | |
|     private func model(withPath path: String) -> SpeechModel {
 | |
|         let model = SpeechModel()
 | |
|         model.path = path
 | |
|         return model
 | |
|     }
 | |
|     
 | |
|     private func timerAction() {
 | |
|         timerCount -= 1
 | |
|         DispatchQueue.main.async {[weak self] in
 | |
|             guard let `self` = self else {
 | |
|                 return
 | |
|             }
 | |
|             currentModel?.timerChangedBlock?(TimeInterval(timerCount/10))
 | |
|         }
 | |
|         if let model = currentModel, model.isPlaying {
 | |
|             if timerCount <= 0 {
 | |
|                 stopPlay(with: model)
 | |
|             }
 | |
|         } else {
 | |
|             timer?.pauseTimer()
 | |
|         }
 | |
|         if timerCount < -10000 {
 | |
|             timerCount = 0
 | |
|         }
 | |
|         //dlog("SpeechManager timerAction___\(timerCount)")
 | |
|     }
 | |
|     
 | |
|     // MARK: - Lazy Timer
 | |
|     private var timerInstance: TimerModel {
 | |
|         if timer == nil {
 | |
|             timer = TimerModel()
 | |
|             timer?.timerBlock = { [weak self] in
 | |
|                 self?.timerAction()
 | |
|             }
 | |
|         }
 | |
|         return timer!
 | |
|     }
 | |
|     
 | |
|     // MARK: - Public Methods
 | |
|     static func checkVoiceState() -> Bool {
 | |
|         // 🔥 Assuming PhoneManager and ChatRoomRoute are external dependencies
 | |
|         if PhoneManager.isInPhoneChannel() || ChatRoomRoute.isChatRoomOpen() {
 | |
|             UIWindow.key?.makeToast("toast_voice_channel_is_occupied")
 | |
|             dlog("toast_voice_channel_is_occupied")
 | |
|             return false
 | |
|         }
 | |
|         return true
 | |
|     }
 | |
|     
 | |
|     func modelWithFilePath(_ path: String) -> SpeechModel {
 | |
|         let model = model(withPath: path)
 | |
|         model.fileType = .file
 | |
|         return model
 | |
|     }
 | |
|     
 | |
|     func modelWithFileUrl(_ url: String) -> SpeechModel {
 | |
|         let model = model(withPath: url)
 | |
|         model.fileType = .url
 | |
|         return model
 | |
|     }
 | |
|     
 | |
|     func modelWithBase64String(_ base64String: String) -> SpeechModel {
 | |
|         let model = model(withPath: base64String)
 | |
|         model.fileType = .base64
 | |
|         return model
 | |
|     }
 | |
|     
 | |
|     func startPlay(with model: SpeechModel) {
 | |
|         guard model.loadState != .loading else { return }
 | |
|         
 | |
|         if currentModel === model {
 | |
|             if currentModel?.isPlaying == true {
 | |
|                 currentModel?.stopPlay()
 | |
|                 return
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         if let current = currentModel {
 | |
|             stopPlay(with: current)
 | |
|         }
 | |
|         
 | |
|         model.canAutoPlay = true
 | |
|         if model.needLoadData() {
 | |
|             model.loadSpeechFile()
 | |
|             currentModel = model
 | |
|         } else {
 | |
|             currentModel = model
 | |
|             timerCount = model.audioTime
 | |
|             model.startPlay()
 | |
|             timerInstance.startTimer()
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func stopPlay(with model: SpeechModel) {
 | |
|         model.canAutoPlay = false
 | |
|         // model.stateChangedBlock = nil
 | |
|         model.stopPlay()
 | |
|         if model === currentModel {
 | |
|             timerInstance.pauseTimer()
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func stopPlayCurrent() {
 | |
|         if let model = currentModel {
 | |
|             stopPlay(with: model)
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| // 🔥 Placeholder for external dependencies
 | |
| class PhoneManager {
 | |
|     static func isInPhoneChannel() -> Bool { return false } // 🔥 Placeholder
 | |
| }
 | |
| 
 | |
| class ChatRoomRoute {
 | |
|     static func isChatRoomOpen() -> Bool { return false } // 🔥 Placeholder
 | |
| }
 |