From 69e8f115afe5c7047bcee85205bf7654d40da279 Mon Sep 17 00:00:00 2001 From: liangzhenying <867174124@qq.com> Date: Fri, 12 Sep 2025 15:08:05 +0800 Subject: [PATCH] =?utf8?q?=E5=AF=B9=E8=AF=9D=E8=AF=B7=E6=B1=82=E5=8A=A0?= =?utf8?q?=E4=BA=86loading?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- ShenYin/Podfile.lock | 10 +- ShenYin/ShenYin.xcodeproj/project.pbxproj | 35 +++++++ .../xcshareddata/swiftpm/Package.resolved | 15 +++ ShenYin/ShenYin/AppLaunch.swift | 10 ++ .../AppIcon.appiconset/20250911-142330.png | Bin 0 -> 21205 bytes .../AppIcon.appiconset/Contents.json | 23 +---- ShenYin/ShenYin/Ble/BleManager.swift | 66 ++++++++------ ShenYin/ShenYin/SceneDelegate.swift | 2 +- ShenYin/ShenYin/UI/Base/BaseTC.swift | 2 +- ShenYin/ShenYin/UI/Home/Chat/ChatCell.swift | 14 ++- ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift | 45 ++++++--- .../Home/FieldRecording/FieldRecordBar.swift | 2 +- .../FieldRecording/FieldRecordingVC.swift | 38 +++++--- .../UI/Home/FieldRecording/RhythView.swift | 16 +++- ShenYin/ShenYin/UI/Mode/CustomEqVC.swift | 1 - ShenYin/ShenYin/UI/Scan/BleScanVC.swift | 73 ++++++++++++++- ShenYin/ShenYin/UI/common/LoadingButton.swift | 60 ++++++++++++ .../UI/common/cache/CacheManager.swift | 62 +++++++++++++ .../UI/common/pop/ConnectPopView.swift | 86 ++++++++++++++++++ ShenYin/podfile | 4 +- 20 files changed, 462 insertions(+), 102 deletions(-) create mode 100644 ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/20250911-142330.png create mode 100644 ShenYin/ShenYin/UI/common/LoadingButton.swift create mode 100644 ShenYin/ShenYin/UI/common/cache/CacheManager.swift create mode 100644 ShenYin/ShenYin/UI/common/pop/ConnectPopView.swift diff --git a/ShenYin/Podfile.lock b/ShenYin/Podfile.lock index be12f21..3e86ec9 100644 --- a/ShenYin/Podfile.lock +++ b/ShenYin/Podfile.lock @@ -52,8 +52,6 @@ PODS: - Moya/Core (= 15.0.0) - Moya/Core (15.0.0): - Alamofire (~> 5.0) - - MultiSlider (2.2.0): - - SweeterSwift - netfox (1.21.0) - Realm (20.0.3): - Realm/Headers (= 20.0.3) @@ -65,7 +63,6 @@ PODS: - SVProgressHUD (2.3.1): - SVProgressHUD/Core (= 2.3.1) - SVProgressHUD/Core (2.3.1) - - SweeterSwift (1.2.6) - SwiftDate (7.0.0) - swiftScan (1.2.1) - TabPageViewController (0.2.8) @@ -89,7 +86,6 @@ DEPENDENCIES: - Kingfisher (~> 6.0) - MJRefresh - Moya - - MultiSlider - netfox - RealmSwift - SnapKit @@ -123,14 +119,12 @@ SPEC REPOS: - Kingfisher - MJRefresh - Moya - - MultiSlider - netfox - Realm - RealmSwift - SnapKit - SocketRocket - SVProgressHUD - - SweeterSwift - SwiftDate - swiftScan - TabPageViewController @@ -158,14 +152,12 @@ SPEC CHECKSUMS: Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee - MultiSlider: 9667217199a051fa729bf54986d68fb9b911554c netfox: 9d5cc727fe7576c4c7688a2504618a156b7d44b7 Realm: 853e5089d6042dff807bda000277eadfe2da93d2 RealmSwift: f33c19577cefcbf681345d721fcbc7b42be4c949 SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22 - SweeterSwift: 1eca266517c703d7376e723a21926f5cb2ba4d0f SwiftDate: bbc26e26fc8c0c33fbee8c140c5e8a68293a148a swiftScan: 0849e7d7c1c641384767a573ee8cb90b88d1ddd9 TabPageViewController: 8bd4104909754416b35a98f3b72a5b674ab20dd5 @@ -174,6 +166,6 @@ SPEC CHECKSUMS: YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 -PODFILE CHECKSUM: 826428f9bd4197f6e9759f68eaf9008f80c0563b +PODFILE CHECKSUM: bc7d3a8004029604d5620b967136223e19d8a67d COCOAPODS: 1.16.2 diff --git a/ShenYin/ShenYin.xcodeproj/project.pbxproj b/ShenYin/ShenYin.xcodeproj/project.pbxproj index de54e87..52afbf1 100644 --- a/ShenYin/ShenYin.xcodeproj/project.pbxproj +++ b/ShenYin/ShenYin.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 3F79C6142E6055E500EC38B9 /* JoyGemAI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */; }; 3F79C6152E6055E500EC38B9 /* JoyGemAI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3FF8A4622E72CBBA00271F9E /* DSWaveformImage in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF8A4612E72CBBA00271F9E /* DSWaveformImage */; }; + 3FF8A4642E72CBBA00271F9E /* DSWaveformImageViews in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF8A4632E72CBBA00271F9E /* DSWaveformImageViews */; }; F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3862D5561144E20721225B96 /* Pods_ShenYin.framework */; }; /* End PBXBuildFile section */ @@ -63,7 +65,9 @@ buildActionMask = 2147483647; files = ( F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */, + 3FF8A4622E72CBBA00271F9E /* DSWaveformImage in Frameworks */, 3F79C6142E6055E500EC38B9 /* JoyGemAI.framework in Frameworks */, + 3FF8A4642E72CBBA00271F9E /* DSWaveformImageViews in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -158,6 +162,9 @@ ); mainGroup = 3F887B932E38D8DC00C98658; minimizedProjectReferenceProxies = 1; + packageReferences = ( + 3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */, + ); preferredProjectObjectVersion = 77; productRefGroup = 3F887B9D2E38D8DC00C98658 /* Products */; projectDirPath = ""; @@ -187,10 +194,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks.sh\"\n"; @@ -457,6 +468,30 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/dmrschmidt/DSWaveformImage"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 14.2.2; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 3FF8A4612E72CBBA00271F9E /* DSWaveformImage */ = { + isa = XCSwiftPackageProductDependency; + package = 3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */; + productName = DSWaveformImage; + }; + 3FF8A4632E72CBBA00271F9E /* DSWaveformImageViews */ = { + isa = XCSwiftPackageProductDependency; + package = 3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */; + productName = DSWaveformImageViews; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 3F887B942E38D8DC00C98658 /* Project object */; } diff --git a/ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..6851bcf --- /dev/null +++ b/ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "eb3e6467aa3b79663b371a20cbe7f1b7c7a6a3c9f98e6945bc9704361b5ae42d", + "pins" : [ + { + "identity" : "dswaveformimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dmrschmidt/DSWaveformImage", + "state" : { + "revision" : "4c56578ee10128ee2b2c04c9c5aa73812de722db", + "version" : "14.2.2" + } + } + ], + "version" : 3 +} diff --git a/ShenYin/ShenYin/AppLaunch.swift b/ShenYin/ShenYin/AppLaunch.swift index 4004d61..eb00957 100644 --- a/ShenYin/ShenYin/AppLaunch.swift +++ b/ShenYin/ShenYin/AppLaunch.swift @@ -13,6 +13,7 @@ class AppLaunch:NSObject{ @MainActor static func start(){ JoySdkManager.shared.setupSdk() setupKeyboard() + loadCache() } @MainActor static func setupKeyboard(){ @@ -23,4 +24,13 @@ class AppLaunch:NSObject{ IQKeyboardManager.shared.isEnabled = true IQKeyboardManager.shared.resignOnTouchOutside = true } + static func loadCache(){ + let list = DeviceCache.shared.getDeviceList() + Logger.debug("缓存设备",list) + if list.count > 0 { + CacheManager.shared.currentDevice = list.first + BleManager.shared.startScanDevice() + App.shared.enter() + } + } } diff --git a/ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/20250911-142330.png b/ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/20250911-142330.png new file mode 100644 index 0000000000000000000000000000000000000000..1484aa2dc5f53bb25f93a4c2ec7ad2d3efb41bbb GIT binary patch literal 21205 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 literal 0 HcmV?d00001 diff --git a/ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/Contents.json index 2305880..ba8a194 100644 --- a/ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ShenYin/ShenYin/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,28 +1,7 @@ { "images" : [ { - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "tinted" - } - ], + "filename" : "20250911-142330.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" diff --git a/ShenYin/ShenYin/Ble/BleManager.swift b/ShenYin/ShenYin/Ble/BleManager.swift index 17c8cc3..88d6639 100644 --- a/ShenYin/ShenYin/Ble/BleManager.swift +++ b/ShenYin/ShenYin/Ble/BleManager.swift @@ -8,7 +8,6 @@ import UIKit import CoreBluetooth import JoyGemAI -import SVProgressHUD import AVFAudio class BleManager: NSObject { var discoverDeviceCallback: (([CBPeripheral]) -> Void)? @@ -66,24 +65,25 @@ extension BleManager:CBCentralManagerDelegate{ } devices.append(peripheral) - print(peripheral) + Logger.debug(peripheral) discoverDeviceCallback?(devices) + checkConnect() } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { stopScanDevice() - print("蓝牙已连接 \(peripheral)") + Logger.debug("蓝牙已连接 \(peripheral)") connectPeripheral = peripheral peripheral.delegate = self peripheral.discoverServices([CBUUID(string: kJoyGemAIServiceUUID)]); didConnectDeviceCallback?(connectPeripheral!) } func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { - print("peripheral: %@ failed to connect", peripheral) - SVProgressHUD.dismiss() + Logger.debug("peripheral: %@ failed to connect", peripheral) + YLprogressHUD.hidden() } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { - print("蓝牙已断开 \(peripheral)") + Logger.debug("蓝牙已断开 \(peripheral)") disConnectDeviceCallback?(peripheral) } } @@ -93,9 +93,9 @@ extension BleManager: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { - print("发现服务成功") + Logger.debug("发现服务成功") for service in peripheral.services! { - print("peripheral service: %@", service) + Logger.debug("peripheral service: %@", service) peripheral.discoverCharacteristics(nil, for: service) } @@ -119,7 +119,7 @@ extension BleManager: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: (any Error)?) { if (characteristic.isNotifying == true && characteristic.service?.uuid.uuidString == kJoyGemAIServiceUUID && characteristic.uuid.uuidString == kJoyGemAICharacteristicNotifyUUID) { //MARK: 使能成功时需要 - print("特征使能成功") + Logger.debug("特征使能成功") JoyGemAIManager.shared().bleConnected() } } @@ -136,26 +136,38 @@ extension BleManager: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: (any Error)?) { } - } extension BleManager{ - // MARK: - Public Methods func startScanDevice() { - print("扫描中...") + centralManager.stopScan() + Logger.debug("扫描中...") devices = [] centralManager.scanForPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)],options: [CBCentralManagerScanOptionAllowDuplicatesKey : false]) + discoverDeviceCallback?(devices) + } + + func checkConnect(){ let list = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)]) for item in list { devices.append(item) break } - if list.count > 0 { - print("缓存",list) + + for item in devices{ + if let current = CacheManager.shared.currentDevice,current.uuid == item.identifier.uuidString { + connectPeripheral(item) + return + } + } + + if connectPeripheral == nil || connectPeripheral?.state == .disconnected { + DispatchQueue.main.asyncAfter(deadline:.now() + 3) { + self.checkConnect() + } } - discoverDeviceCallback?(devices) } func stopScanDevice() { @@ -163,13 +175,9 @@ extension BleManager{ } func connectPeripheral(_ peripheral: CBPeripheral) { - print("连接中...") -// YLprogressHUD.showLoading() + Logger.debug("连接中...") centralManager.connect(peripheral, options: [CBConnectPeripheralOptionEnableTransportBridgingKey:true]) - SVProgressHUD.show(withStatus: "连接中") - // DispatchQueue.main.asyncAfter(deadline: .now() + 15){[weak self] in - // self?.cancel() - // } + YLprogressHUD.showLoading() } func cancel() { @@ -185,32 +193,32 @@ extension BleManager : JoyGemAIManagerDelegate { } func joyGemAuthSuccessCallback() { - YLprogressHUD.showAutoHiden(text: "鉴权成功"){ + ConnectPopView().showAutoHide { App.shared.enter() } - + CacheManager.shared.saveDevice(DeviceModel(name: connectPeripheral?.name ?? "", uuid: connectPeripheral?.identifier.uuidString ?? "")) PcmSound.sharedInstance().setup(16000, withchannels: 1) let options: AVAudioSession.CategoryOptions = [.allowBluetooth] do { try AVAudioSession.sharedInstance().setCategory(.playback, options: [options]) try AVAudioSession.sharedInstance().setActive(true) } catch { - print(error) + Logger.debug(error) } } func joyGemAction(_ action: JoyGemActionMode) { switch action { case .cancel: - SVProgressHUD.showInfo(withStatus: "请求关闭录音功能/通知关闭了对话") + YLprogressHUD.showAutoHiden("请求关闭录音功能/通知关闭了对话") case .recordLive: - SVProgressHUD.showInfo(withStatus: "请求开启现场录音") + YLprogressHUD.showAutoHiden("请求开启现场录音") case .recordCall: - SVProgressHUD.showInfo(withStatus: "请求开启通话录音") + YLprogressHUD.showAutoHiden("请求开启通话录音") case .si: - SVProgressHUD.showInfo(withStatus: "请求开启同传听译") + YLprogressHUD.showAutoHiden( "请求开启同传听译") case .chat: - SVProgressHUD.showInfo(withStatus: "通知开启了AI对话") + YLprogressHUD.showAutoHiden( "通知开启了AI对话") @unknown default: break } diff --git a/ShenYin/ShenYin/SceneDelegate.swift b/ShenYin/ShenYin/SceneDelegate.swift index a191bc1..c891392 100644 --- a/ShenYin/ShenYin/SceneDelegate.swift +++ b/ShenYin/ShenYin/SceneDelegate.swift @@ -20,7 +20,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { App.shared.window = window window?.rootViewController = BaseTC() - window?.rootViewController = UINavigationController(rootViewController: CustomEqVC()) + window?.rootViewController = UINavigationController(rootViewController: BleScanVC()) AppLaunch.start() } diff --git a/ShenYin/ShenYin/UI/Base/BaseTC.swift b/ShenYin/ShenYin/UI/Base/BaseTC.swift index 0ef49d6..06eddf7 100644 --- a/ShenYin/ShenYin/UI/Base/BaseTC.swift +++ b/ShenYin/ShenYin/UI/Base/BaseTC.swift @@ -55,6 +55,6 @@ class BaseTC:UITabBarController{ self.tabBar.backgroundColor = .white view.backgroundColor = .color(.bgColor) - self.selectedIndex = 1 + self.selectedIndex = 0 } } diff --git a/ShenYin/ShenYin/UI/Home/Chat/ChatCell.swift b/ShenYin/ShenYin/UI/Home/Chat/ChatCell.swift index 71cb86f..cfb25ea 100644 --- a/ShenYin/ShenYin/UI/Home/Chat/ChatCell.swift +++ b/ShenYin/ShenYin/UI/Home/Chat/ChatCell.swift @@ -8,11 +8,11 @@ public class ChatCellModel { public var type: Int = 0//1发,0收 public var content: String = "" - public var id:UInt = 0 + public var id:Int = 0 } class ChatCell:BaseTableViewCell{ - let bgView = UIView() + let bgView = LoadingView() let originalLabel = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -54,13 +54,20 @@ class ChatCell:BaseTableViewCell{ make.top.bottom.equalToSuperview().inset(14) make.left.right.equalToSuperview().inset(12) make.width.lessThanOrEqualTo(kScreenWid - 60) + make.width.greaterThanOrEqualTo(60) + make.height.greaterThanOrEqualTo(19) } } var data:ChatCellModel!{ didSet{ if data.content.isEmpty{ - data.content = "..." + originalLabel.text = "" + bgView.startAnimating() + } + else{ + bgView.stopAnimating() + originalLabel.text = data.content } if data.type == 1 { bgView.backgroundColor = .color(.theme) @@ -80,7 +87,6 @@ class ChatCell:BaseTableViewCell{ make.left.equalToSuperview().inset(20) } } - originalLabel.text = data.content } } } diff --git a/ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift b/ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift index fda5200..bd3982b 100644 --- a/ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift +++ b/ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift @@ -134,7 +134,15 @@ class ChatVC:BaseVC{ extension ChatVC:ChatRecordBarDelegate{ func recordBarStart(_ toolBar: ChatRecordBar) { -// JoyGemChatManager.shared().playAudioEnd() + + let model = ChatCellModel() + model.type = 1 + model.content = "" + model.id = -1 + dataList.append(model) + tableView.reloadData() + scrollToBottom() + JoyGemChatManager.shared().stopChat() JoyGemChatManager.shared().startSingleChat() } @@ -199,20 +207,27 @@ extension ChatVC : JoyGemChatManagerDelegate { func chatManager(_ manager: JoyGemChatManager, requestText text: String?, index: UInt) { Logger.debug(text,index) - if let text = text { - if let model = dataList.last,model.id == index,model.type == 1 { - model.content = text - } - else{ - let model = ChatCellModel() - model.type = 1 - model.content = text - model.id = index - dataList.append(model) - } - tableView.reloadData() - scrollToBottom() + guard let text = text else{ + return + } + if text.isEmpty { + return + } + if dataList.last?.id == -1 { + dataList.removeLast() + } + if let model = dataList.last,model.id == index,model.type == 1 { + model.content = text + } + else{ + let model = ChatCellModel() + model.type = 1 + model.content = text + model.id = Int(index) + dataList.append(model) } + tableView.reloadData() + scrollToBottom() } func chatManager(_ manager: JoyGemChatManager, responseText text: String?, index: UInt, finish isFinish: Bool) { @@ -226,7 +241,7 @@ extension ChatVC : JoyGemChatManagerDelegate { let model = ChatCellModel() model.type = 0 model.content = text - model.id = index + model.id = Int(index) dataList.append(model) } tableView.reloadData() diff --git a/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordBar.swift b/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordBar.swift index 575baca..018aaaf 100644 --- a/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordBar.swift +++ b/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordBar.swift @@ -19,7 +19,7 @@ protocol FieldRecordBarDelegate { class FieldRecordBar: BaseView { - let recordBtn = UIButton() + let recordBtn = LoadingButton() let leftItem = RecordBarItem() let rightItem = RecordBarButton() var state:RecordSate = .stop diff --git a/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift b/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift index b7cc559..75a807a 100644 --- a/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift +++ b/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift @@ -86,14 +86,17 @@ extension FieldRecordingVC:FieldRecordBarDelegate{ } else if state == .stop{ JoyGemRecordManager.shared().stop() - - let v = PopTextField() - v.show() - v.cancelTap = { - - } - v.okTap = { - + bar.recordBtn.startAnimating {[weak self] in + guard let self = self else{return} +// toolBar.recordBtn.stopCli() + let v = PopTextField() + v.show() + v.cancelTap = { + + } + v.okTap = { + + } } } } @@ -144,12 +147,21 @@ extension FieldRecordingVC : JoyGemRecordManagerDelegate { func recordManagerStopped(_ manager: JoyGemRecordManager, reason code: JoyGemRecordStopCode) { -// if (code == .actively) { + if (code == .actively) { // YLprogressHUD.showAutoHiden("用户主动结束") -// } else { -// YLprogressHUD.showAutoHiden("自动结束") -// ///判断当前蓝牙是否连接从而确定是否因为蓝牙断开造成的录音断开 -// } +// toolBar.recordBtn.stopLoading() +// let v = PopTextField() +// v.show() +// v.cancelTap = { +// +// } +// v.okTap = { +// +// } + } else { + YLprogressHUD.showAutoHiden("自动结束") + ///判断当前蓝牙是否连接从而确定是否因为蓝牙断开造成的录音断开 + } } func recordManager(_ manager: JoyGemRecordManager, onError code: JoyGemErrorCode) { diff --git a/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift b/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift index 76371dd..2b837ad 100644 --- a/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift +++ b/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift @@ -1,5 +1,17 @@ import UIKit +//import DSWaveformImage -class RhythView: UIView { - +class RhythView: BaseView { +// let wave = WaveformLiveView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 50)) +// +// override func setupViews() { +// backgroundColor = .red +// wave.backgroundColor = .green +// addSubview(wave) +// +// } +// override func setupLayout() { +// +// } + } diff --git a/ShenYin/ShenYin/UI/Mode/CustomEqVC.swift b/ShenYin/ShenYin/UI/Mode/CustomEqVC.swift index 184680f..870c17b 100644 --- a/ShenYin/ShenYin/UI/Mode/CustomEqVC.swift +++ b/ShenYin/ShenYin/UI/Mode/CustomEqVC.swift @@ -7,7 +7,6 @@ import UIKit import JoyGemAI -import MultiSlider class CustomEqVC:BaseVC{ private let bgView = UIView() private let sliderBgView = UIView() diff --git a/ShenYin/ShenYin/UI/Scan/BleScanVC.swift b/ShenYin/ShenYin/UI/Scan/BleScanVC.swift index 37dc8ea..aa11e6a 100644 --- a/ShenYin/ShenYin/UI/Scan/BleScanVC.swift +++ b/ShenYin/ShenYin/UI/Scan/BleScanVC.swift @@ -8,7 +8,15 @@ import UIKit import CoreBluetooth import DGActivityIndicatorView + +enum BleScanState{ + case scan + case has + case none +} + class BleScanVC: BaseVC{ + let headerView = BleScanHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 280)) let tableView = UITableView(frame: .zero, style: .plain) var list:[CBPeripheral] = [] @@ -25,7 +33,7 @@ class BleScanVC: BaseVC{ v.estimatedRowHeight = 76 v.separatorStyle = .none v.register(BleScanCell.self, forCellReuseIdentifier: BleScanCell.reuseID) - v.tableHeaderView = BleScanHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 280)) + v.tableHeaderView = headerView } view.addSubview(tableView) } @@ -39,6 +47,12 @@ class BleScanVC: BaseVC{ BleManager.shared.discoverDeviceCallback = {[weak self] devices in self?.list = devices self?.tableView.reloadData() + if devices.count > 0 { + self?.headerView.stateView.state = .has + } + else{ + self?.headerView.stateView.state = .none + } } startScan() } @@ -48,7 +62,7 @@ class BleScanVC: BaseVC{ func startScan(){ list = [] tableView.reloadData() - BleManager.shared.startScanDevice() + BleManager.shared.startScanDevice() } } @@ -72,10 +86,11 @@ extension BleScanVC:UITableViewDelegate,UITableViewDataSource { class BleScanHeaderView: BaseView { let rippleView = DGActivityIndicatorView(type: .triplePulse,tintColor: UIColor.hexString("#0092E1"),size: 250)! var radarImageView = UIImageView() + var stateView = ScanView() override func setupViews() { backgroundColor = .clear // rippleView.backgroundColor = .red - addSubviews([rippleView,radarImageView]) + addSubviews([rippleView,radarImageView,stateView]) rippleView.startAnimating() radarImageView.do { v in @@ -101,6 +116,58 @@ class BleScanHeaderView: BaseView { make.size.equalTo(250) make.center.equalToSuperview() } + stateView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(rippleView.snp.bottom).offset(30) + } + } + + + + class ScanView: BaseView { + let titleLabel = UILabel() + let desLabel = UILabel() + var state:BleScanState = .scan{ + didSet{ + self.isHidden = state == .has + if state == .none { +// titleLabel.text = "正在扫描" +// desLabel.text = "请确保智能设备已连接电源,且位于手机附近" + } + else{ + titleLabel.text = "正在扫描" + desLabel.text = "请确保智能设备已连接电源,且位于手机附近" + } + } + } + override func setupViews() { + backgroundColor = .clear + addSubviews([titleLabel,desLabel]) + titleLabel.do { (v) in + v.textColor = .rgb(0x121212) + v.font = .regular(14) + v.textAlignment = .center + v.numberOfLines = 0 + } + desLabel.do { (v) in + v.textColor = .rgb(0x8D8D8D) + v.font = .regular(14) + v.textAlignment = .center + v.numberOfLines = 0 + } + } + override func setupLayout() { + titleLabel.snp.makeConstraints { make in + make.top.equalToSuperview() + make.centerX.equalToSuperview() + } + desLabel.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(10) + make.centerX.equalToSuperview() + } + } + + } } diff --git a/ShenYin/ShenYin/UI/common/LoadingButton.swift b/ShenYin/ShenYin/UI/common/LoadingButton.swift new file mode 100644 index 0000000..464b106 --- /dev/null +++ b/ShenYin/ShenYin/UI/common/LoadingButton.swift @@ -0,0 +1,60 @@ +// +// LoadingButton.swift +// ShenYin +// +// Created by liangshi on 2025/9/11. +// +import DGActivityIndicatorView +import UIKit +class LoadingButton:UIButton{ + let loadingView = DGActivityIndicatorView(type: .ballClipRotate,tintColor: UIColor.hexString("#0092E1"))! + + override init(frame: CGRect) { + super.init(frame: frame) + loadingView.backgroundColor = .white + addSubview(loadingView) + loadingView.snp.remakeConstraints { make in + make.edges.equalToSuperview() + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + func startAnimating(finished:(()->Void)? = nil){ + loadingView.startAnimating() + DispatchQueue.main.asyncAfter(deadline:.now() + 3) { + self.stopAnimating() + finished?() + } + } + func stopAnimating(){ + loadingView.stopAnimating() + } +} + +class LoadingView: UIView { + let activeView = DGActivityIndicatorView(type: .ballPulse,tintColor: .white)! + + override init(frame: CGRect) { + super.init(frame: frame) + activeView.backgroundColor = .clear + addSubview(activeView) + activeView.snp.makeConstraints { make in + make.center.equalToSuperview() + make.width.equalTo(60) + make.height.equalTo(40) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func startAnimating(finished:(()->Void)? = nil){ + activeView.startAnimating() + } + func stopAnimating(){ + activeView.stopAnimating() + } +} diff --git a/ShenYin/ShenYin/UI/common/cache/CacheManager.swift b/ShenYin/ShenYin/UI/common/cache/CacheManager.swift new file mode 100644 index 0000000..5f2f202 --- /dev/null +++ b/ShenYin/ShenYin/UI/common/cache/CacheManager.swift @@ -0,0 +1,62 @@ +// +// c.swift +// ShenYin +// +// Created by liangshi on 2025/9/11. +// +import CoreBluetooth + +class CacheManager{ + static let shared = CacheManager() + var currentDevice:DeviceModel? + + func saveDevice(_ device: DeviceModel) { + self.currentDevice = device + DeviceCache.shared.saveDevice(device) + } +} + +class DeviceModel: NSObject, NSCoding { + var name = "" + var uuid = "" + + init(name: String, uuid: String) { + self.name = name + self.uuid = uuid + } + + func encode(with aCoder: NSCoder) { + aCoder.encode(name, forKey: "name") + aCoder.encode(uuid, forKey: "uuid") + } + + required init?(coder aDecoder: NSCoder) { + name = aDecoder.decodeObject(forKey: "name") as? String ?? "" + uuid = aDecoder.decodeObject(forKey: "uuid") as? String ?? "" + } +} + +class DeviceCache { + static let shared = DeviceCache() + private let userDefaults = UserDefaults.standard + private let deviceListKey = "deviceListKey" + + func saveDevice(_ device: DeviceModel) { + var deviceList = getDeviceList() + if let index = deviceList.firstIndex(where: { $0.uuid == device.uuid }) { + deviceList[index] = device + } else { + deviceList.append(device) + } + let encoder = NSKeyedArchiver.archivedData(withRootObject: deviceList) + userDefaults.set(encoder, forKey: deviceListKey) + } + + func getDeviceList() -> [DeviceModel] { + if let data = userDefaults.data(forKey: deviceListKey), + let deviceList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [DeviceModel] { + return deviceList + } + return [] + } +} diff --git a/ShenYin/ShenYin/UI/common/pop/ConnectPopView.swift b/ShenYin/ShenYin/UI/common/pop/ConnectPopView.swift new file mode 100644 index 0000000..82879e3 --- /dev/null +++ b/ShenYin/ShenYin/UI/common/pop/ConnectPopView.swift @@ -0,0 +1,86 @@ +// +// ConnectPopView.swift +// ShenYin +// +// Created by liangshi on 2025/9/11. +// + +import UIKit + +class ConnectPopView: BasePresentView2 { + let contentView = UIView() + private let titleLabel = UILabel() + private let imageView = UIImageView() + private let desLabel = UILabel() + + + init() { + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func setupSubView() { + super.setupSubView() + addSubview(contentView) + contentView.addSubviews([titleLabel,imageView,desLabel]) + } + override func setupLayout() { + super.setupLayout() + + contentView.snp.makeConstraints { make in + make.left.right.equalToSuperview().inset(18) + make.height.equalTo(315) + make.center.equalToSuperview() + } + titleLabel.snp.makeConstraints { (m) in + m.top.equalToSuperview().inset(30) + m.left.right.equalToSuperview() + } + imageView.snp.makeConstraints { (m) in + m.centerX.equalToSuperview() + m.top.equalToSuperview().inset(76) + m.width.equalTo(190) + m.height.equalTo(156) + } + desLabel.snp.makeConstraints { (m) in + m.top.equalTo(imageView.snp.bottom).offset(20) + m.left.right.equalToSuperview() +// m.bottom.equalToSuperview().inset(30) + } + } + + override func setupStyle() { + super.setupStyle() + contentView.do { (v) in + v.backgroundColor = .white + v.yc.setCornerRadius(20) + } + imageView.do { v in + v.image = UIImage(named: "home_header") + } + titleLabel.do { (v) in + v.textColor = .rgb(0x121212) + v.font = .regular(20) + v.textAlignment = .center + v.text = "Deep Gen2 Max" + } + desLabel.do { (v) in + v.textColor = .rgb(0x121212) + v.font = .regular(24) + v.textAlignment = .center + v.text = "连接成功" + } + } + + func showAutoHide(finished: (() -> Void)? = nil){ + show() + DispatchQueue.main.asyncAfter(deadline:.now() + 0.5) { + self.hide() + finished?() + } + } +} + diff --git a/ShenYin/podfile b/ShenYin/podfile index 55c4a07..fee0b8d 100644 --- a/ShenYin/podfile +++ b/ShenYin/podfile @@ -32,7 +32,9 @@ target 'ShenYin' do pod 'SocketRocket'#socket,AI用到 pod 'DGActivityIndicatorView'#扫描雷达 - pod 'MultiSlider' +# pod 'MultiSlider' +# pod 'DSWaveformImage' + # pod 'NVActivityIndicatorView', '~> 5.1.1' # 最新稳定版 # pod 'EZAudio', '~> 1.1.0' end -- 2.17.1