From: liangzhenying <867174124@qq.com> Date: Fri, 26 Sep 2025 03:50:51 +0000 (+0800) Subject: 完善UI X-Git-Tag: 1.0.2~96 X-Git-Url: http://git.snicker.com.cn/Users/apple/Desktop/static/gitweb.css?a=commitdiff_plain;h=5866bd99a36b6ed5fe85866739c57e65cc96e411;p=mirrors%2FShenYin.git 完善UI --- diff --git a/ShenYin/ShenYin/Assets.xcassets/home/lvdong.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/lvdong.imageset/Contents.json new file mode 100644 index 0000000..4feb1b9 --- /dev/null +++ b/ShenYin/ShenYin/Assets.xcassets/home/lvdong.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "lvdong@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShenYin/ShenYin/Assets.xcassets/home/lvdong.imageset/lvdong@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/lvdong.imageset/lvdong@2x.png new file mode 100644 index 0000000..aeac888 Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/lvdong.imageset/lvdong@2x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Contents.json new file mode 100644 index 0000000..4591384 --- /dev/null +++ b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group 2095@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group 2095@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Group 2095@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Group 2095@2x.png new file mode 100644 index 0000000..6417b96 Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Group 2095@2x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Group 2095@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Group 2095@3x.png new file mode 100644 index 0000000..9444543 Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_1.imageset/Group 2095@3x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Contents.json new file mode 100644 index 0000000..c31e30f --- /dev/null +++ b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group 2290@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group 2290@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Group 2290@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Group 2290@2x.png new file mode 100644 index 0000000..b90caf4 Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Group 2290@2x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Group 2290@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Group 2290@3x.png new file mode 100644 index 0000000..3fe6ff1 Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_2.imageset/Group 2290@3x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Contents.json new file mode 100644 index 0000000..ba69c16 --- /dev/null +++ b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group 2291@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group 2291@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Group 2291@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Group 2291@2x.png new file mode 100644 index 0000000..78d610c Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Group 2291@2x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Group 2291@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Group 2291@3x.png new file mode 100644 index 0000000..a1f0cb6 Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_white_3.imageset/Group 2291@3x.png differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/Contents.json new file mode 100644 index 0000000..5446c99 --- /dev/null +++ b/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "分屏_2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "分屏_2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/\345\210\206\345\261\217_2@2x.png" "b/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/\345\210\206\345\261\217_2@2x.png" new file mode 100644 index 0000000..0a43345 Binary files /dev/null and "b/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/\345\210\206\345\261\217_2@2x.png" differ diff --git "a/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/\345\210\206\345\261\217_2@3x.png" "b/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/\345\210\206\345\261\217_2@3x.png" new file mode 100644 index 0000000..5cbb614 Binary files /dev/null and "b/ShenYin/ShenYin/Assets.xcassets/home/split_screen_2.imageset/\345\210\206\345\261\217_2@3x.png" differ diff --git a/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/Contents.json new file mode 100644 index 0000000..884debb --- /dev/null +++ b/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "语音发送中@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "语音发送中@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/\350\257\255\351\237\263\345\217\221\351\200\201\344\270\255@2x.png" "b/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/\350\257\255\351\237\263\345\217\221\351\200\201\344\270\255@2x.png" new file mode 100644 index 0000000..de5c375 Binary files /dev/null and "b/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/\350\257\255\351\237\263\345\217\221\351\200\201\344\270\255@2x.png" differ diff --git "a/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/\350\257\255\351\237\263\345\217\221\351\200\201\344\270\255@3x.png" "b/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/\350\257\255\351\237\263\345\217\221\351\200\201\344\270\255@3x.png" new file mode 100644 index 0000000..60cb958 Binary files /dev/null and "b/ShenYin/ShenYin/Assets.xcassets/home/translate_bg.imageset/\350\257\255\351\237\263\345\217\221\351\200\201\344\270\255@3x.png" differ diff --git a/ShenYin/ShenYin/MixApi/MixApi.swift b/ShenYin/ShenYin/MixApi/MixApi.swift deleted file mode 100644 index 177778b..0000000 --- a/ShenYin/ShenYin/MixApi/MixApi.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// MixApi.swift -// Magpie -// -// Created by incar on 2024/1/6. -// - -import Foundation -import CoreBluetooth - -public class MixDevice{ - - /// 设备 - var peripheral: CBPeripheral! - - /// 广播信息 - var advertisementData: [String : AnyObject]? - - /// 信号 - var RSSI: Int32? -} - -public protocol MixApi { - - /// 单利 - static var manager: MixApi { get } - - /// 发现设备 - var discoverDevice:((_ devices:[MixDevice]) -> Void)? { get } - - /// 收到sdk传数过来的数据,具体请阅读每条指令参数说明 - var receiveData:((_ data:Any) -> Void)? { get } - - /// 扫描 - /// - Parameters: - /// - uuid: 指定设备 - /// - duration: 超时 - func scanWithServices(_ uuid: [String]?, duration: TimeInterval) - - /// 停止扫描 - func stopScan() - - /// 连接设备 - /// - Parameters: - /// - device: 扫描到的涉笔 - /// - duration: 超时时间 - /// - success: 连接成功 - /// - fail: 连接失败 - func connect(device : MixDevice, duration: TimeInterval, success: @escaping (() -> Void), fail: @escaping ((_ error:[String:Any]) -> Void)) - - /// 连接设备 - /// - Parameters: - /// - identifier: 设备标识符 - /// - duration: 超时时间 - /// - success: 连接成功 - /// - fail: 连接失败 - func connect(identifier : String, duration: TimeInterval, success: @escaping (() -> Void), fail: @escaping ((_ error:[String:Any]) -> Void)) - - - /// 取消当前连接 - func cancelConnect() - - /// 发送指令 - /// - Parameters: - /// - parameters: 无参传nil,具体key-value请阅读每条指令参数说明 - /// - success: 发送成功 - /// - failure: 发送失败 - func sendCommand(parameters: [String : Any]?, success:@escaping (() -> Void), failure:@escaping ((_ error:[String:Any]) -> Void)) -} diff --git a/ShenYin/ShenYin/Tools/YLTools.swift b/ShenYin/ShenYin/Tools/YLTools.swift new file mode 100644 index 0000000..03dacb5 --- /dev/null +++ b/ShenYin/ShenYin/Tools/YLTools.swift @@ -0,0 +1,16 @@ +// +// YLTools.swift +// ShenYin +// +// Created by liangshi on 2025/9/22. +// +import Foundation + +class YLToos { + static func formatSeconds(_ totalSeconds: Int) -> String { + let hours = totalSeconds / 3600 + let minutes = (totalSeconds % 3600) / 60 + let seconds = totalSeconds % 60 + return String(format: "%02d:%02d:%02d", hours, minutes, seconds) + } +} diff --git a/ShenYin/ShenYin/UI/Home/CallingRecordVC.swift b/ShenYin/ShenYin/UI/Home/CallingRecordVC.swift index d27735f..e8f88d5 100644 --- a/ShenYin/ShenYin/UI/Home/CallingRecordVC.swift +++ b/ShenYin/ShenYin/UI/Home/CallingRecordVC.swift @@ -38,7 +38,6 @@ class CallingRecordVC:BaseVC{ override func setupLayout() { rhythView.snp.makeConstraints { make in make.width.centerX.equalToSuperview() - make.height.equalTo(100) make.top.equalToSuperview().inset(kNavBtm) } toolBar.snp.makeConstraints { make in @@ -66,11 +65,12 @@ class CallingRecordVC:BaseVC{ } override func navleftViewTapped() { if toolBar.recordBtn.isSelected { - CustomAlert.showWith(title: "提示", messgage: "当前正在录音,确定放弃当前录音吗?", cancelCallback: nil) { + CustomAlert.showWith(title: "提示", messgage: "当前正在录音,确定放弃当前录音吗?", cancelCallback: nil) {[unowned self] in + self.rhythView.stopTimer() JoyGemCallManager.shared().stop() PcmSound.sharedInstance().stopAudioUnit() PcmSound.sharedInstance().cleanup() - super.navleftViewTapped() + self.navigationController?.popViewController(animated: true) } } else{ @@ -105,9 +105,11 @@ extension CallingRecordVC:FieldRecordBarDelegate{ if state == .start { textView.text = "" messageList.removeAll() + rhythView.startTimer() JoyGemCallManager.shared().start() } else if state == .stop{ + rhythView.stopTimer() JoyGemCallManager.shared().stop() bar.startAnimating {[weak self] in guard let self = self else{return} diff --git a/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift b/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift index 138ff35..0c3e100 100644 --- a/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift +++ b/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift @@ -11,12 +11,17 @@ import AVFAudio class Chinese2EnglishVC:BaseVC{ let toolBar = RecordBar() let tableView = UITableView(frame: CGRectZero, style: .plain) + let bg = UIImageView() var dataList:[(Chinese2EnglishCellModel,UInt)] = [] var pcmData = Data() override func setupViews() { navBar.title = "中英互译" navBar.rightView.setImage(UIImage(named: "help_icon"), for: .normal) + view.addSubview(tableView) + view.addSubview(toolBar) + view.addSubview(bg) + toolBar.delegate = self tableView.backgroundColor = .clear @@ -25,8 +30,9 @@ class Chinese2EnglishVC:BaseVC{ tableView.estimatedRowHeight = 60 tableView.separatorStyle = .none tableView.register(Chinese2EnglishCell.self, forCellReuseIdentifier: Chinese2EnglishCell.reuseID) - view.addSubview(tableView) - view.addSubview(toolBar) + + bg.image = UIImage(named: "translate_bg") + } override func setupLayout() { @@ -40,6 +46,10 @@ class Chinese2EnglishVC:BaseVC{ make.left.right.equalToSuperview() make.bottom.equalTo(toolBar.snp.top) } + bg.snp.makeConstraints { make in + make.size.equalTo(90) + make.center.equalTo(tableView) + } } override func setupData() { JoyGemSIDeviceManager.shared().delegate = self @@ -81,6 +91,10 @@ class Chinese2EnglishVC:BaseVC{ tableView.reloadData() if dataList.count > 0 { tableView.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true) + bg.isHidden = true + } + else{ + bg.isHidden = false } } } diff --git a/ShenYin/ShenYin/UI/Home/Dialog/DialogRecordBar.swift b/ShenYin/ShenYin/UI/Home/Dialog/DialogRecordBar.swift index fd644a5..23b82ff 100644 --- a/ShenYin/ShenYin/UI/Home/Dialog/DialogRecordBar.swift +++ b/ShenYin/ShenYin/UI/Home/Dialog/DialogRecordBar.swift @@ -23,180 +23,228 @@ protocol DialogRecordBarDelegate { } class DialogRecordBar: BaseView { - let switchBtn = UIButton() - let leftItem = RecordBarItem() - let rightItem = RecordBarItem() + let recordView = DialogRecordView() + let languageView = DialogLanguageView() var delegate:DialogRecordBarDelegate? + var navBar:BaseNavigationBar = BaseNavigationBar() override func setupViews() { - backgroundColor = .white - addSubviews([leftItem,rightItem,switchBtn]) + backgroundColor = .clear + addSubviews([recordView,languageView]) - switchBtn.do { v in - v.setImage(UIImage(named: "split_screen_1"), for: .normal) - v.setImage(UIImage(named: "split_screen_1"), for: .selected) - v.addTarget(self, action: #selector(switchBtnAction), for: .touchUpInside) + recordView.do { v in +// v.backgroundColor = .green + v.switchBtn.addTarget(self, action: #selector(switchBtnAction), for: .touchUpInside) + v.leftRecord.addTarget(self, action: #selector(leftRecordBtnAction), for: .touchUpInside) + v.rightRecord.addTarget(self, action: #selector(rightRecordBtnAction), for: .touchUpInside) } - leftItem.do { (v) in - v.recordBtn.setImage(UIImage(named: "dialog_device_ear"), for: .normal) - v.recordBtn.setImage(UIImage(named: "dialog_device_ear"), for: .selected) - v.languageItem.language = AiSupportLanguage.chinse - v.languageItem.yc.addTap(target: self, action: #selector(leftLanguageAction)) - v.recordBtn.addTarget(self, action: #selector(leftRecordBtnAction), for: .touchUpInside) - v.language = .chinse - } - rightItem.do { (v) in - v.recordBtn.setImage(UIImage(named: "dialog_device_phone"), for: .normal) - v.recordBtn.setImage(UIImage(named: "dialog_device_phone"), for: .selected) - v.languageItem.language = AiSupportLanguage.english - v.languageItem.yc.addTap(target: self, action: #selector(rightLanguageAction)) - v.recordBtn.addTarget(self, action: #selector(rightRecordBtnAction), for: .touchUpInside) - v.language = .english + languageView.do { (v) in + v.leftItem.yc.addTap(target: self, action: #selector(leftLanguageAction)) + v.rightItem.yc.addTap(target: self, action: #selector(rightLanguageAction)) } } override func setupLayout() { - switchBtn.snp.makeConstraints { make in - make.size.equalTo(56) - make.center.equalToSuperview() - } - leftItem.snp.makeConstraints { make in - make.height.equalTo(100) - make.centerY.equalTo(switchBtn) - make.right.equalToSuperview().offset(-(kScreenWid/2 + 60)) + recordView.snp.makeConstraints { make in + make.width.equalToSuperview() + make.height.equalTo(34) + make.top.equalToSuperview().inset(10) + make.left.equalToSuperview() } - rightItem.snp.makeConstraints { make in - make.height.equalTo(100) - make.centerY.equalTo(switchBtn) - make.left.equalToSuperview().offset(kScreenWid/2 + 60) + languageView.snp.makeConstraints { make in + make.width.equalToSuperview() + make.top.equalTo(recordView.snp.bottom) + make.left.equalToSuperview() +// make.height.equalTo(60) } } - func stopRecord(){ - if leftItem.recordBtn.isSelected { - leftItem.recordBtn.isSelected = false - leftItem.stopAnimating() + func stopRecord(_ type:DialogRecordDeviceType){ + if type == .earphone { + recordView.leftRecord.isSelected = false + recordView.leftRecord.stopAnimating(finished: { [weak self] in + guard let self = self else { return } + recordView.leftRecord.alpha = 1 + languageView.leftItem.alpha = 1 + recordView.rightRecord.alpha = 1 + languageView.rightItem.alpha = 1 + }) } - if rightItem.recordBtn.isSelected { - rightItem.recordBtn.isSelected = false - rightItem.stopAnimating() + else{ + recordView.rightRecord.isSelected = false + recordView.rightRecord.stopAnimating(finished: { [weak self] in + guard let self = self else { return } + recordView.leftRecord.alpha = 1 + languageView.leftItem.alpha = 1 + recordView.rightRecord.alpha = 1 + languageView.rightItem.alpha = 1 + }) } - leftItem.alpha = 1 - rightItem.alpha = 1 } @objc func switchBtnAction(){ - delegate?.recordBar(self, layoutChange: .normal) + recordView.switchBtn.isSelected = !recordView.switchBtn.isSelected + let type:DialogRecordLayoutType = recordView.switchBtn.isSelected ? .spolit:.normal + delegate?.recordBar(self, layoutChange: type) + + if type == .normal { + navBar.titleLabel.isHidden = false + recordView.addSubview(recordView.rightRecord) + recordView.setupLayout() + } + else{ + recordView.splitLayout() + + navBar.titleLabel.isHidden = true + navBar.addSubview(recordView.rightRecord) + recordView.rightRecord.snp.makeConstraints { make in + make.center.equalTo(navBar.titleLabel) + } + } } @objc func leftRecordBtnAction(){ - if rightItem.recordBtn.activeView.animating { - return - } - if rightItem.recordBtn.isSelected { + if recordView.rightRecord.activeView.animating || recordView.rightRecord.loadView.animating { return } - leftItem.recordBtn.isSelected = !leftItem.recordBtn.isSelected - if leftItem.recordBtn.isSelected { - rightItem.recordBtn.alpha = 1 - leftItem.languageItem.alpha = 0.3 - rightItem.recordBtn.alpha = 0.3 - rightItem.languageItem.alpha = 0.3 + + recordView.leftRecord.isSelected = !recordView.leftRecord.isSelected + if recordView.leftRecord.isSelected { + recordView.leftRecord.alpha = 1 + recordView.rightRecord.alpha = 0.3 + languageView.leftItem.alpha = 0.3 + languageView.rightItem.alpha = 0.3 - leftItem.startAnimating() + recordView.leftRecord.startAnimating() delegate?.recordBar(self, device: .earphone,stateChange: .start) } else{ - leftItem.recordBtn.alpha = 1 - leftItem.languageItem.alpha = 1 - rightItem.recordBtn.alpha = 1 - rightItem.languageItem.alpha = 1 - - leftItem.stopAnimating() + stopRecord(.earphone) delegate?.recordBar(self, device: .earphone,stateChange: .stop) } } @objc func rightRecordBtnAction(){ - if leftItem.recordBtn.activeView.animating { + if recordView.leftRecord.activeView.animating || recordView.leftRecord.loadView.animating { return } - if leftItem.recordBtn.isSelected { - return - } - rightItem.recordBtn.isSelected = !rightItem.recordBtn.isSelected - if rightItem.recordBtn.isSelected { - leftItem.recordBtn.alpha = 0.3 - leftItem.languageItem.alpha = 0.3 - rightItem.recordBtn.alpha = 1 - rightItem.languageItem.alpha = 0.3 + recordView.rightRecord.isSelected = !recordView.rightRecord.isSelected + + if recordView.rightRecord.isSelected { + recordView.leftRecord.alpha = 0.3 + recordView.rightRecord.alpha = 1 + languageView.leftItem.alpha = 0.3 + languageView.rightItem.alpha = 0.3 - rightItem.startAnimating() + recordView.rightRecord.startAnimating() delegate?.recordBar(self, device: .phone,stateChange: .start) } else{ - leftItem.recordBtn.alpha = 1 - leftItem.languageItem.alpha = 1 - rightItem.recordBtn.alpha = 1 - rightItem.languageItem.alpha = 1 - - rightItem.stopAnimating() + stopRecord(.phone) delegate?.recordBar(self, device: .phone,stateChange: .stop) } } @objc func leftLanguageAction(){ - if leftItem.recordBtn.isSelected || rightItem.recordBtn.isSelected { + if recordView.isBusy { return } - let v = LanguagePickerView(languages: AiSupportLanguage.translate,isLeft: true,left: leftItem.language,right: rightItem.language) - v.selectedIndex = v.list.firstIndex(where: {$0.title == leftItem.language.title}) ?? 0 + let v = LanguagePickerView(languages: AiSupportLanguage.translate,isLeft: true,left: languageView.leftItem.language,right: languageView.rightItem.language) + v.selectedIndex = v.list.firstIndex(where: {$0.title == languageView.leftItem.language.title}) ?? 0 v.show() v.didSelected = {[weak self] (index,value) in guard let self = self else { return } if index == 0 { - leftItem.language = value + languageView.leftItem.language = value } else{ - rightItem.language = value + languageView.rightItem.language = value } } } @objc func rightLanguageAction(){ - if leftItem.recordBtn.isSelected || rightItem.recordBtn.isSelected{ + if recordView.isBusy{ return } - let v = LanguagePickerView(languages: AiSupportLanguage.translate,isLeft: false,left: leftItem.language,right: rightItem.language) - v.selectedIndex = v.list.firstIndex(where: {$0.title == rightItem.language.title}) ?? 0 + let v = LanguagePickerView(languages: AiSupportLanguage.translate,isLeft: false,left: languageView.leftItem.language,right: languageView.rightItem.language) + v.selectedIndex = v.list.firstIndex(where: {$0.title == languageView.rightItem.language.title}) ?? 0 v.show() v.didSelected = {[weak self] (index,value) in guard let self = self else { return } if index == 0 { - leftItem.language = value + languageView.leftItem.language = value } else{ - rightItem.language = value + languageView.rightItem.language = value } } } - class RecordBarItem: UIView { - let recordBtn = RecordingButton() - let languageItem = RecordLanguageItem() + class DialogRecordView:BaseView{ + let leftRecord = DialogRecordingButton() + let rightRecord = DialogRecordingButton() + let switchBtn = UIButton() + var isBusy:Bool{ + return leftRecord.activeView.animating || leftRecord.loadView.animating || rightRecord.activeView.animating || rightRecord.loadView.animating + } - var language:AiSupportLanguage = AiSupportLanguage.chinse{ - didSet{ - languageItem.language = language + override func setupViews() { + addSubviews([leftRecord,rightRecord,switchBtn]) + switchBtn.do { v in + v.setImage(UIImage(named: "split_screen_1"), for: .normal) + v.setImage(UIImage(named: "split_screen_2"), for: .selected) +// v.backgroundColor = .red + + } + leftRecord.do { v in + v.setImage(UIImage(named: "dialog_device_ear"), for: .normal) + v.setImage(UIImage(named: "dialog_device_ear"), for: .selected) + } + rightRecord.do { v in + v.setImage(UIImage(named: "dialog_device_phone"), for: .normal) + v.setImage(UIImage(named: "dialog_device_phone"), for: .selected) + v.activeView.tintColor = UIColor.hexString("#0092E1") + v.activeView.yc.setBorder(width: 2, color: .hexString("#0092E1"), radius: 17) + v.loadView.tintColor = UIColor.hexString("#0092E1") } } - - func startAnimating(){ - recordBtn.startAnimating() + override func setupLayout() { + switchBtn.snp.remakeConstraints { make in + make.size.equalTo(34) + make.centerX.equalToSuperview() + make.top.equalToSuperview() + } + leftRecord.snp.remakeConstraints { make in + make.width.equalTo(66) + make.height.equalTo(34) + make.top.equalToSuperview().inset(0) + make.right.equalToSuperview().offset(-(kScreenWid/2 + 60)) + } + rightRecord.snp.remakeConstraints { make in + make.width.equalTo(66) + make.height.equalTo(34) + make.top.equalToSuperview().inset(0) + make.left.equalToSuperview().offset(kScreenWid/2 + 60) + } } - func stopAnimating(){ - recordBtn.stopAnimating() + func splitLayout(){ + switchBtn.snp.remakeConstraints { make in + make.size.equalTo(34) + make.right.equalToSuperview().inset(36) + make.top.equalToSuperview() + } + leftRecord.snp.remakeConstraints { make in + make.width.equalTo(66) + make.height.equalTo(34) + make.top.equalToSuperview().inset(0) + make.right.equalToSuperview().offset(-(kScreenWid/2 - 33)) + } } + } + class DialogLanguageView: UIView { + let leftItem = RecordLanguageItem() + let rightItem = RecordLanguageItem() override init(frame: CGRect) { super.init(frame: frame) @@ -210,25 +258,33 @@ class DialogRecordBar: BaseView { func setupViews() { // backgroundColor = .red - addSubviews([recordBtn,languageItem]) - recordBtn.do { v in -// v.yc.setBorder(width: 1, color: .color(.theme), radius: 17) + addSubviews([leftItem,rightItem]) + + leftItem.do { (v) in + v.language = AiSupportLanguage.chinse + v.yc.addTap(target: self, action: #selector(leftLanguageAction)) + v.language = .chinse + v.valueLabel.text = "耳机" + } + rightItem.do { (v) in + v.language = AiSupportLanguage.english + v.yc.addTap(target: self, action: #selector(rightLanguageAction)) + v.language = .english + v.valueLabel.text = "手机" } } func setupLayout() { - recordBtn.snp.makeConstraints { make in - make.width.equalTo(66) - make.height.equalTo(34) - make.top.equalToSuperview().inset(0) - make.centerX.equalToSuperview() + leftItem.snp.makeConstraints { make in + make.height.equalTo(60) + make.top.equalToSuperview() + make.right.equalToSuperview().offset(-(kScreenWid/2 + 60)) } - languageItem.snp.makeConstraints { make in - make.right.equalToSuperview() - make.top.equalTo(recordBtn.snp.bottom).offset(0) - make.centerX.equalToSuperview() + rightItem.snp.makeConstraints { make in + make.height.equalTo(leftItem) + make.centerY.equalTo(leftItem) + make.left.equalToSuperview().offset(kScreenWid/2 + 60) } - } } class RecordLanguageItem: BaseView { @@ -255,7 +311,6 @@ class DialogRecordBar: BaseView { valueLabel.do { v in v.textColor = .rgb(0x666666) v.font = .regular(10) - v.text = "耳机" } } diff --git a/ShenYin/ShenYin/UI/Home/Dialog/DialogSplitView.swift b/ShenYin/ShenYin/UI/Home/Dialog/DialogSplitView.swift new file mode 100644 index 0000000..8c99724 --- /dev/null +++ b/ShenYin/ShenYin/UI/Home/Dialog/DialogSplitView.swift @@ -0,0 +1,214 @@ +// +// Dialog.swift +// ShenYin +// +// Created by liangshi on 2025/9/25. +// + +import UIKit + +class DialogSplitView: BaseView { + let line = UIView() + let tableView1 = UITableView(frame: CGRectZero, style: .plain) + var dataList1:[DialogTranslateCellModel] = [] + + let tableView2 = UITableView(frame: CGRectZero, style: .plain) + var dataList2:[DialogTranslateCellModel] = [] + + var dataList:[DialogTranslateCellModel] = []{ + didSet{ + dataList1 = dataList + dataList2 = dataList + tableView1.reloadData() + tableView2.reloadData() + + if dataList.count > 0 { + tableView1.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true) + tableView2.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true) + } + + } + } + + override func setupViews() { + addSubviews([tableView1,tableView2,line]) + +// backgroundColor = .red + tableView1.do { v in + v.backgroundColor = .hexString("#F7F7F7") +// v.backgroundColor = .green + v.delegate = self + v.dataSource = self + v.estimatedRowHeight = 60 + v.separatorStyle = .none + v.register(DialogSplitCell.self, forCellReuseIdentifier: DialogSplitCell.reuseID) + v.transform = CGAffineTransform(rotationAngle: .pi) + } + tableView2.do { v in + v.backgroundColor = .hexString("#F7F7F7") +// v.backgroundColor = .yellow + v.delegate = self + v.dataSource = self + v.estimatedRowHeight = 60 + v.separatorStyle = .none + v.register(DialogSplitCell.self, forCellReuseIdentifier: DialogSplitCell.reuseID) + } + line.backgroundColor = .hexString("#E9E9E9") + } + override func setupLayout() { + tableView1.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.equalToSuperview() + make.width.equalTo(kScreenWid) + make.height.equalToSuperview().multipliedBy(0.5) + } + tableView2.snp.makeConstraints { make in + make.top.equalTo(tableView1.snp.bottom) + make.left.equalToSuperview() + make.width.equalTo(kScreenWid) + make.height.equalToSuperview().multipliedBy(0.5) + } + line.snp.makeConstraints { make in + make.left.right.equalToSuperview().inset(36) + make.top.equalTo(tableView2.snp.top ) + make.height.equalTo(1) + } + } + +} +extension DialogSplitView:UITableViewDelegate,UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if tableView == tableView1 { + return dataList1.count + } + else { + return dataList2.count + } + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = DialogSplitCell.cell(withTableView: tableView, indexPath: indexPath) + if tableView == tableView1 { + cell.config(data: dataList1[indexPath.row], isLeft: false) + } + else{ + cell.config(data: dataList1[indexPath.row], isLeft: true) + } + return cell + } + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + } +} + +class DialogSplitCell:BaseTableViewCell{ + let bgView = UIView() + let originalLabel = UILabel() + let copyIcon = UIImageView() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func setupViews() { + contentView.backgroundColor = .hexString("#F7F7F7") + + bgView.do { v in + v.yc.setCornerRadius(12) + v.backgroundColor = .white + } + originalLabel.do { v in + v.font = .regular(14) + v.textColor = .hexString("#121212") + v.numberOfLines = 0 + v.textAlignment = .left + } + copyIcon.do { v in + v.image = UIImage(named: "play_animate_3") + v.animationImages = [UIImage(named: "play_animate_1")!,UIImage(named: "play_animate_2")!,UIImage(named: "play_animate_3")!] + v.animationDuration = 0.6 + v.animationRepeatCount = 0 + v.yc.addTap(target: self, action: #selector(copyAction)) + } + contentView.addSubview(bgView) + bgView.addSubviews([originalLabel,copyIcon]) + } + + override func setupLayout() { + originalLabel.snp.makeConstraints { make in + make.top.equalToSuperview().inset(14) + make.height.greaterThanOrEqualTo(15) + make.left.equalToSuperview().inset(12) + make.width.lessThanOrEqualTo(kScreenWid - 120) + make.right.equalToSuperview().inset(50) + make.bottom.equalToSuperview().inset(14) + } + copyIcon.snp.makeConstraints { make in + make.right.equalToSuperview().inset(12) + make.size.equalTo(24) + make.top.equalToSuperview().inset(12) + } + } + + + func config(data:DialogTranslateCellModel,isLeft:Bool){ + + // translationLabel.text = data.response + if isLeft { + if data.isPhone { + originalLabel.text = data.response + bgView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) + make.right.equalToSuperview().inset(18) + } + bgView.backgroundColor = .color(.theme) + originalLabel.textColor = .white + } + else{ + originalLabel.text = data.send + bgView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) + make.left.equalToSuperview().inset(18) + } + bgView.backgroundColor = .white + originalLabel.textColor = .hexString("#606D80") + } + } + else{ + if data.isPhone { + originalLabel.text = data.send + bgView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) + make.right.equalToSuperview().inset(18) + } + bgView.backgroundColor = .color(.theme) + originalLabel.textColor = .white + } + else{ + originalLabel.text = data.response + bgView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) + make.left.equalToSuperview().inset(18) + } + bgView.backgroundColor = .white + originalLabel.textColor = .hexString("#606D80") + } + } + } + + @objc func copyAction(){ + // UIPasteboard.general.string = data.send + "\n" + data.response + // YLprogressHUD.showAutoHiden("已拷贝") + if copyIcon.isAnimating { + copyIcon.stopAnimating() + } + else{ + copyIcon.startAnimating() + } + } +} diff --git a/ShenYin/ShenYin/UI/Home/Dialog/DialogTranlateVC.swift b/ShenYin/ShenYin/UI/Home/Dialog/DialogTranlateVC.swift index 7f8263d..90333d7 100644 --- a/ShenYin/ShenYin/UI/Home/Dialog/DialogTranlateVC.swift +++ b/ShenYin/ShenYin/UI/Home/Dialog/DialogTranlateVC.swift @@ -12,6 +12,7 @@ class DialogTranslateVC:BaseVC{ let toolBar = DialogRecordBar() var recordFilePath : String? + let splitView = DialogSplitView() let tableView = UITableView(frame: CGRectZero, style: .plain) var dataList:[DialogTranslateCellModel] = [] @@ -23,14 +24,15 @@ class DialogTranslateVC:BaseVC{ super.viewDidLoad() } override func setupViews() { - view.addSubviews([toolBar,tableView]) + view.addSubviews([toolBar,tableView,splitView]) navBar.title = "对话翻译" navBar.rightView.setImage(UIImage(named: "help_icon"), for: .normal) toolBar.do { v in - v.backgroundColor = .clear +// v.backgroundColor = .clear v.delegate = self + v.navBar = navBar } view.backgroundColor = .hexString("#F7F7F7") @@ -42,12 +44,14 @@ class DialogTranslateVC:BaseVC{ v.separatorStyle = .none v.register(DialogTranslateCell.self, forCellReuseIdentifier: DialogTranslateCell.reuseID) } + splitView.isHidden = true + } override func setupLayout() { toolBar.snp.makeConstraints { make in make.width.centerX.equalToSuperview() make.height.equalTo(120) - make.bottom.equalToSuperview().inset(20) + make.bottom.equalToSuperview() } tableView.snp.makeConstraints { make in make.top.equalToSuperview().inset(kNavBtm) @@ -55,8 +59,17 @@ class DialogTranslateVC:BaseVC{ make.width.equalTo(kScreenWid) make.bottom.equalTo(toolBar.snp.top) } + splitView.snp.makeConstraints { make in + make.edges.equalTo(tableView) + } } override func setupData() { +// dataList = [ +// DialogTranslateCellModel(send: "你好", response: "hello",isPhone: false), +// DialogTranslateCellModel(send: "Nice to meet you", response: "很高兴认识你",isPhone: true), +// DialogTranslateCellModel(send: "深圳今天下雨吗", response: "ShenZhen is raining today?",isPhone: false), +// DialogTranslateCellModel(send: "YES", response: "是的",isPhone: true), +// ] JoyGemSIManager.shared().delegate = self JoyGemSIDeviceManager.shared().delegate = self @@ -83,18 +96,11 @@ class DialogTranslateVC:BaseVC{ navigationController?.fd_fullscreenPopGestureRecognizer?.isEnabled = true } override func navleftViewTapped() { - if toolBar.leftItem.recordBtn.isSelected || toolBar.rightItem.recordBtn.isSelected { - CustomAlert.showWith(title: "提示", messgage: "当前正在录音,确定放弃当前录音吗?", cancelCallback: nil) { - JoyGemSIManager.shared().stop() - JoyGemSIDeviceManager.shared().stop() - PcmSound.sharedInstance().stopAudioUnit() - PcmSound.sharedInstance().cleanup() - super.navleftViewTapped() - } - } - else{ - super.navleftViewTapped() - } + JoyGemSIManager.shared().stop() + JoyGemSIDeviceManager.shared().stop() + PcmSound.sharedInstance().stopAudioUnit() + PcmSound.sharedInstance().cleanup() + super.navleftViewTapped() } func refreshData(){ @@ -102,6 +108,7 @@ class DialogTranslateVC:BaseVC{ if dataList.count > 0 { tableView.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true) } + splitView.dataList = dataList } } @@ -122,7 +129,13 @@ extension DialogTranslateVC:UITableViewDelegate,UITableViewDataSource { extension DialogTranslateVC:DialogRecordBarDelegate{ func recordBar(_ bar: DialogRecordBar, layoutChange: DialogRecordLayoutType) { - + if layoutChange == .spolit{ + splitView.isHidden = false + splitView.dataList = dataList + } + else{ + splitView.isHidden = true + } } func recordBar(_ bar: DialogRecordBar, device: DialogRecordDeviceType, stateChange state: RecordBarSate) { @@ -152,8 +165,8 @@ extension DialogTranslateVC:DialogRecordBarDelegate{ dataList.append(model) refreshData() - JoyGemSIManager.shared().originalLanguage = toolBar.rightItem.language.value - JoyGemSIManager.shared().targetLanguage = toolBar.leftItem.language.value + JoyGemSIManager.shared().originalLanguage = toolBar.languageView.rightItem.language.value + JoyGemSIManager.shared().targetLanguage = toolBar.languageView.leftItem.language.value JoyGemSIManager.shared().start() } @@ -169,8 +182,8 @@ extension DialogTranslateVC:DialogRecordBarDelegate{ dataList.append(model) refreshData() - JoyGemSIDeviceManager.shared().originalLanguage = toolBar.leftItem.language.value - JoyGemSIDeviceManager.shared().targetLanguage = toolBar.rightItem.language.value + JoyGemSIManager.shared().originalLanguage = toolBar.languageView.leftItem.language.value + JoyGemSIManager.shared().targetLanguage = toolBar.languageView.rightItem.language.value JoyGemSIDeviceManager.shared().start() otherPcm = Data() do { @@ -188,7 +201,10 @@ extension DialogTranslateVC:DialogRecordBarDelegate{ extension DialogTranslateVC : JoyGemSIManagerDelegate { func siManagerStopped(_ manager: JoyGemSIManager, reason code: JoyGemRecordStopCode) { - + if let model = dataList.last,model.send.isEmpty{ + dataList.removeLast() + refreshData() + } } func siManager(_ manager: JoyGemSIManager, didUpdateRaw model: JoyGemAsrModel) { @@ -203,6 +219,7 @@ extension DialogTranslateVC : JoyGemSIManagerDelegate { ///监听到一句话结束,自动结束当前录音 if (model.definite == true) { + toolBar.stopRecord(.phone) stopPhoneRecord() } @@ -261,7 +278,10 @@ extension DialogTranslateVC : JoyGemSIManagerDelegate { extension DialogTranslateVC : JoyGemSIDeviceManagerDelegate { func siDeviceManagerStopped(_ manager: JoyGemSIDeviceManager, reason code: JoyGemRecordStopCode) { - + if let model = dataList.last,model.send.isEmpty{ + dataList.removeLast() + refreshData() + } } func siDeviceManager(_ manager: JoyGemSIDeviceManager, didUpdateRaw model: JoyGemAsrModel) { @@ -277,6 +297,7 @@ extension DialogTranslateVC : JoyGemSIDeviceManagerDelegate { ///监听到一句话结束,自动结束当前录音 if (model.definite == true) { + toolBar.stopRecord(.earphone) stopEarRecord() } diff --git a/ShenYin/ShenYin/UI/Home/Dialog/DialogTranslateCell.swift b/ShenYin/ShenYin/UI/Home/Dialog/DialogTranslateCell.swift index 952387e..b98a949 100644 --- a/ShenYin/ShenYin/UI/Home/Dialog/DialogTranslateCell.swift +++ b/ShenYin/ShenYin/UI/Home/Dialog/DialogTranslateCell.swift @@ -10,9 +10,10 @@ class DialogTranslateCellModel{ var response = "" var isPhone : Bool = false //是否手机收音 - init(send: String = "", response: String = "") { + init(send: String = "", response: String = "",isPhone : Bool = false) { self.send = send self.response = response + self.isPhone = isPhone } } @@ -55,7 +56,7 @@ class DialogTranslateCell:BaseTableViewCell{ v.textAlignment = .left } line.do { v in - // v.backgroundColor = .hexString("#93C6EC") + v.backgroundColor = .hexString("#93C6EC") } copyIcon.do { v in v.image = UIImage(named: "play_animate_3") @@ -69,17 +70,18 @@ class DialogTranslateCell:BaseTableViewCell{ } override func setupLayout() { - bgView.snp.makeConstraints { make in - make.top.bottom.equalToSuperview().inset(10) - make.width.lessThanOrEqualTo(kScreenWid - 58) - make.left.equalToSuperview().inset(18) - } - +// bgView.snp.makeConstraints { make in +// make.top.bottom.equalToSuperview().inset(10) +// make.width.lessThanOrEqualTo(kScreenWid - 58) +// make.left.equalToSuperview().inset(18) +// } +// originalLabel.snp.makeConstraints { make in make.top.equalToSuperview().inset(14) - make.left.equalToSuperview().inset(12) make.height.greaterThanOrEqualTo(15) - make.width.lessThanOrEqualTo(kScreenWid - 110) + make.left.equalToSuperview().inset(12) + make.right.equalToSuperview().inset(50) + make.width.lessThanOrEqualTo(kScreenWid - 120) } line.snp.makeConstraints { make in make.left.right.equalToSuperview().inset(12) @@ -90,7 +92,7 @@ class DialogTranslateCell:BaseTableViewCell{ translationLabel.snp.makeConstraints { make in make.top.equalTo(line.snp.bottom).offset(15) make.left.equalToSuperview().inset(12) - make.width.lessThanOrEqualTo(kScreenWid - 110) + make.right.equalToSuperview().inset(12) make.height.greaterThanOrEqualTo(15) make.bottom.equalToSuperview().inset(14) } @@ -107,26 +109,27 @@ class DialogTranslateCell:BaseTableViewCell{ translationLabel.text = data.response if data.isPhone { -// bgView.snp.remakeConstraints { make in -// make.top.bottom.equalToSuperview().inset(10) -// make.width.lessThanOrEqualTo(kScreenWid - 58) -// make.left.equalToSuperview().inset(18) -// } + bgView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) +// make.width.equalTo(kScreenWid - 78) + make.right.equalToSuperview().inset(18) + } bgView.backgroundColor = .color(.theme) originalLabel.textColor = .white translationLabel.textColor = .white } else{ + bgView.snp.remakeConstraints { make in + make.top.bottom.equalToSuperview().inset(10) +// make.width.equalTo(kScreenWid - 78) + make.left.equalToSuperview().inset(18) + } bgView.backgroundColor = .white - originalLabel.textColor = .hexString("606D80") + originalLabel.textColor = .hexString("#606D80") translationLabel.textColor = .hexString("#121212") -// bgView.snp.remakeConstraints { make in -// make.top.bottom.equalToSuperview().inset(10) -// make.width.lessThanOrEqualTo(kScreenWid - 58) -// make.right.equalToSuperview().inset(18) -// } - } + line.setNeedsLayout() + line.layoutIfNeeded() } } @objc func copyAction(){ diff --git a/ShenYin/ShenYin/UI/Home/Dialog/Untitled.swift b/ShenYin/ShenYin/UI/Home/Dialog/Untitled.swift new file mode 100644 index 0000000..c7b5846 --- /dev/null +++ b/ShenYin/ShenYin/UI/Home/Dialog/Untitled.swift @@ -0,0 +1,7 @@ +// +// Untitled.swift +// ShenYin +// +// Created by liangshi on 2025/9/25. +// + diff --git a/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift b/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift index d8ba505..8c65613 100644 --- a/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift +++ b/ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift @@ -34,7 +34,6 @@ class FieldRecordingVC:BaseVC{ override func setupLayout() { rhythView.snp.makeConstraints { make in make.width.centerX.equalToSuperview() - make.height.equalTo(100) make.top.equalToSuperview().inset(kNavBtm) } toolBar.snp.makeConstraints { make in @@ -71,11 +70,12 @@ class FieldRecordingVC:BaseVC{ } override func navleftViewTapped() { if toolBar.recordBtn.isSelected { - CustomAlert.showWith(title: "提示", messgage: "当前正在录音,确定放弃当前录音吗?", cancelCallback: nil) { + CustomAlert.showWith(title: "提示", messgage: "当前正在录音,确定放弃当前录音吗?", cancelCallback: nil) {[unowned self] in + self.rhythView.stopTimer() JoyGemRecordManager.shared().stop() PcmSound.sharedInstance().stopAudioUnit() PcmSound.sharedInstance().cleanup() - super.navleftViewTapped() + self.navigationController?.popViewController(animated: true) } } else{ @@ -98,14 +98,18 @@ extension FieldRecordingVC:FieldRecordBarDelegate{ textView.text = "" messageList.removeAll() JoyGemRecordManager.shared().start() + rhythView.startTimer() } if state == .resume{ + rhythView.startTimer() JoyGemRecordManager.shared().resume() } else if state == .pause{ JoyGemRecordManager.shared().pause() + rhythView.stopTimer() } else if state == .stop{ + rhythView.stopTimer() JoyGemRecordManager.shared().stop() bar.startAnimating {[weak self] in guard let self = self else{return} diff --git a/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift b/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift index 2b837ad..1ea5b00 100644 --- a/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift +++ b/ShenYin/ShenYin/UI/Home/FieldRecording/RhythView.swift @@ -2,16 +2,46 @@ import UIKit //import DSWaveformImage class RhythView: BaseView { + let lable = UILabel() + let wave = UIView() + var timer:Timer? + var num = 0 // let wave = WaveformLiveView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 50)) -// -// override func setupViews() { + + override func setupViews() { + addSubviews([lable,wave]) + lable.do { v in + v.textColor = .hexString("#121212") + v.font = .bold(32) + v.textAlignment = .center + v.text = "00:00:00" + } // backgroundColor = .red -// wave.backgroundColor = .green -// addSubview(wave) -// -// } -// override func setupLayout() { -// -// } - + wave.backgroundColor = .lightGray + } + override func setupLayout() { + lable.snp.makeConstraints { make in + make.top.equalToSuperview().inset(10) + make.centerX.equalToSuperview() + } + wave.snp.makeConstraints { make in + make.top.equalToSuperview().inset(40) + make.left.right.equalToSuperview() + make.height.equalTo(58) + make.bottom.equalToSuperview() + } + } + @objc func timerAction(){ + num += 1 + lable.text = YLToos.formatSeconds(num) + } + func startTimer(){ + if let timer = timer,timer.isValid{ + timer.invalidate() + } + timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true) + } + func stopTimer(){ + timer?.invalidate() + } } diff --git a/ShenYin/ShenYin/UI/Home/Root/HomeFunctionView.swift b/ShenYin/ShenYin/UI/Home/Root/HomeFunctionView.swift index fd4d4f6..49557e2 100644 --- a/ShenYin/ShenYin/UI/Home/Root/HomeFunctionView.swift +++ b/ShenYin/ShenYin/UI/Home/Root/HomeFunctionView.swift @@ -78,6 +78,7 @@ class HomeFunctionView: BaseView { var y = 0.0 for (index, value) in list.enumerated() { let view = HomeCell() + view.enable = App.shared.deviceValid addSubview(view) view.type = value @@ -93,10 +94,14 @@ class HomeFunctionView: BaseView { } } } + NotificationManager.add(self, selector: #selector(deviceChange(_:)), forName: .deviceValidChange) } - - override func setupLayout() { - + @objc func deviceChange(_ noti:Notification){ + for item in self.subviews{ + if let view = item as? HomeCell { + view.enable = App.shared.deviceValid + } + } } } class HomeCell: BaseView { @@ -111,6 +116,16 @@ class HomeCell: BaseView { icon.image = UIImage(named: type.icon) } } + var enable:Bool = false{ + didSet{ + if enable { + alpha = 1 + } + else{ + alpha = 0.3 + } + } + } override func setupViews() { addSubview(bgView) @@ -155,6 +170,9 @@ class HomeCell: BaseView { } } @objc func tapAction(){ + if !App.shared.deviceValid { + return + } switch type { case .fileRecord: App.shared.goToPage(FieldRecordingVC()) diff --git a/ShenYin/ShenYin/UI/Home/Root/HomeHeadView.swift b/ShenYin/ShenYin/UI/Home/Root/HomeHeadView.swift index 655a7d1..a940d84 100644 --- a/ShenYin/ShenYin/UI/Home/Root/HomeHeadView.swift +++ b/ShenYin/ShenYin/UI/Home/Root/HomeHeadView.swift @@ -14,6 +14,17 @@ class HomeHeadView: BaseView { let titleLabel = UILabel() let valueLabel = UILabel() + var enable:Bool = false{ + didSet{ + if enable { + bottonView.alpha = 1 + } + else{ + bottonView.alpha = 0.3 + } + } + } + override func setupViews() { addSubviews([icon,bottonView]) bottonView.addSubviews([titleLabel,valueLabel,tipsIcon]) @@ -39,6 +50,8 @@ class HomeHeadView: BaseView { v.font = .regular(14) v.text = "随时随地 一键开录" } + self.enable = App.shared.deviceValid + NotificationManager.add(self, selector: #selector(deviceChange(_:)), forName: .deviceValidChange) } override func setupLayout() { @@ -66,7 +79,12 @@ class HomeHeadView: BaseView { } } @objc func chatAction(){ - App.shared.goToPage(ChatVC()) + if App.shared.deviceValid { + App.shared.goToPage(ChatVC()) + } + } + @objc func deviceChange(_ noti:Notification){ + self.enable = App.shared.deviceValid } } diff --git a/ShenYin/ShenYin/UI/Home/TextTranslate/TextTranslateVC.swift b/ShenYin/ShenYin/UI/Home/TextTranslate/TextTranslateVC.swift index bacf365..ae05b9e 100644 --- a/ShenYin/ShenYin/UI/Home/TextTranslate/TextTranslateVC.swift +++ b/ShenYin/ShenYin/UI/Home/TextTranslate/TextTranslateVC.swift @@ -84,9 +84,10 @@ extension TextTranlateVC:UITableViewDelegate,UITableViewDataSource { } extension TextTranlateVC:SendToolBarDelegate{ func sendToolBar(_ toolBar: SendToolBar, _ text: String) { -// toolBar.textField.resignFirstResponder() + toolBar.textField.resignFirstResponder() dataList.append(TranslateCellModel(send: text,response: "")) refreshData() + toolBar.textField.text = "" let from = languageItem.leftLabel.language.value let to = languageItem.rightLabel.language.value diff --git a/ShenYin/ShenYin/UI/common/AiSupportLanguage.swift b/ShenYin/ShenYin/UI/Launch/AiSupportLanguage.swift similarity index 100% rename from ShenYin/ShenYin/UI/common/AiSupportLanguage.swift rename to ShenYin/ShenYin/UI/Launch/AiSupportLanguage.swift diff --git a/ShenYin/ShenYin/AppDelegate.swift b/ShenYin/ShenYin/UI/Launch/AppDelegate.swift similarity index 100% rename from ShenYin/ShenYin/AppDelegate.swift rename to ShenYin/ShenYin/UI/Launch/AppDelegate.swift diff --git a/ShenYin/ShenYin/AppLaunch.swift b/ShenYin/ShenYin/UI/Launch/AppLaunch.swift similarity index 99% rename from ShenYin/ShenYin/AppLaunch.swift rename to ShenYin/ShenYin/UI/Launch/AppLaunch.swift index d021252..50f4af0 100644 --- a/ShenYin/ShenYin/AppLaunch.swift +++ b/ShenYin/ShenYin/UI/Launch/AppLaunch.swift @@ -8,7 +8,6 @@ import UIKit import IQKeyboardManagerSwift - class AppLaunch:NSObject{ @MainActor static func start(){ JoySdkManager.shared.setupSdk() diff --git a/ShenYin/ShenYin/UI/common/AppManager.swift b/ShenYin/ShenYin/UI/Launch/AppManager.swift similarity index 93% rename from ShenYin/ShenYin/UI/common/AppManager.swift rename to ShenYin/ShenYin/UI/Launch/AppManager.swift index 9edb7d6..f06e6f1 100644 --- a/ShenYin/ShenYin/UI/common/AppManager.swift +++ b/ShenYin/ShenYin/UI/Launch/AppManager.swift @@ -9,7 +9,6 @@ class App{ static let shared = App() var window:UIWindow? - func topVC()->UIViewController!{ guard let vc = window?.rootViewController else{ Logger.debug("页面异常!!!") @@ -42,3 +41,9 @@ extension App{ } } } + +extension App{ + var deviceValid:Bool{ + return BleManager.shared.isConnetd + } +} diff --git a/ShenYin/ShenYin/Ble/BleManager.swift b/ShenYin/ShenYin/UI/Launch/BleManager.swift similarity index 96% rename from ShenYin/ShenYin/Ble/BleManager.swift rename to ShenYin/ShenYin/UI/Launch/BleManager.swift index 2d28d4c..6f3c078 100644 --- a/ShenYin/ShenYin/Ble/BleManager.swift +++ b/ShenYin/ShenYin/UI/Launch/BleManager.swift @@ -25,6 +25,7 @@ class BleManager: NSObject { } static let shared = BleManager() + var isConnetd:Bool = false func setupJoySdk(){ JoyGemAIManager.shared().delegate = self; @@ -84,7 +85,10 @@ extension BleManager:CBCentralManagerDelegate{ } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { Logger.debug("蓝牙已断开 \(peripheral)") + self.isConnetd = false + NotificationManager.post(type: .deviceValidChange, objtect: nil) disConnectDeviceCallback?(peripheral) + checkConnect() } } @@ -102,7 +106,6 @@ extension BleManager: CBPeripheralDelegate { } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { - //MARK: 需要配置服务对象 if (service.uuid.uuidString == kJoyGemAIServiceUUID) { let success = JoyGemAIManager.shared().configService(service) { chars in for char in chars { @@ -121,6 +124,7 @@ extension BleManager: CBPeripheralDelegate { //MARK: 使能成功时需要 Logger.debug("特征使能成功") JoyGemAIManager.shared().bleConnected() + } } @@ -177,7 +181,6 @@ extension BleManager{ func connectPeripheral(_ peripheral: CBPeripheral) { Logger.debug("连接中...") centralManager.connect(peripheral, options: [CBConnectPeripheralOptionEnableTransportBridgingKey:true]) - YLprogressHUD.showLoading() } func cancel() { @@ -193,6 +196,8 @@ extension BleManager : JoyGemAIManagerDelegate { } func joyGemAuthSuccessCallback() { + self.isConnetd = true + NotificationManager.post(type: .deviceValidChange, objtect: nil) ConnectPopView().showAutoHide { App.shared.enter() } diff --git a/ShenYin/ShenYin/UI/common/cache/CacheManager.swift b/ShenYin/ShenYin/UI/Launch/CacheManager.swift similarity index 100% rename from ShenYin/ShenYin/UI/common/cache/CacheManager.swift rename to ShenYin/ShenYin/UI/Launch/CacheManager.swift diff --git a/ShenYin/ShenYin/JoySdkManager.swift b/ShenYin/ShenYin/UI/Launch/JoySdkManager.swift similarity index 100% rename from ShenYin/ShenYin/JoySdkManager.swift rename to ShenYin/ShenYin/UI/Launch/JoySdkManager.swift diff --git a/ShenYin/ShenYin/SceneDelegate.swift b/ShenYin/ShenYin/UI/Launch/SceneDelegate.swift similarity index 100% rename from ShenYin/ShenYin/SceneDelegate.swift rename to ShenYin/ShenYin/UI/Launch/SceneDelegate.swift diff --git a/ShenYin/ShenYin/UI/common/BrokenLineView.swift b/ShenYin/ShenYin/UI/common/BrokenLineView.swift index e96c8f2..faf8df4 100644 --- a/ShenYin/ShenYin/UI/common/BrokenLineView.swift +++ b/ShenYin/ShenYin/UI/common/BrokenLineView.swift @@ -6,22 +6,22 @@ // class BrokenLineView: UIView { - override func draw(_ rect: CGRect) { - super.draw(rect) - let path = UIBezierPath() - let lineWidth: CGFloat = 0.5 - let dashLength: CGFloat = 5.0 - let spaceLength: CGFloat = 3.0 - let startPoint = CGPoint(x: 0, y: bounds.midY) - let endPoint = CGPoint(x: bounds.width, y: bounds.midY) - path.move(to: startPoint) - path.addLine(to: endPoint) - let shapeLayer = CAShapeLayer() - shapeLayer.path = path.cgPath - shapeLayer.strokeColor = UIColor.hexString("#93C6EC").cgColor - shapeLayer.fillColor = UIColor.clear.cgColor - shapeLayer.lineWidth = lineWidth - shapeLayer.lineDashPattern = [NSNumber(value: dashLength), NSNumber(value: spaceLength)] - layer.addSublayer(shapeLayer) - } +// override func draw(_ rect: CGRect) { +// super.draw(rect) +// let path = UIBezierPath() +// let lineWidth: CGFloat = 0.5 +// let dashLength: CGFloat = 5.0 +// let spaceLength: CGFloat = 3.0 +// let startPoint = CGPoint(x: 0, y: bounds.midY) +// let endPoint = CGPoint(x: bounds.width, y: bounds.midY) +// path.move(to: startPoint) +// path.addLine(to: endPoint) +// let shapeLayer = CAShapeLayer() +// shapeLayer.path = path.cgPath +// shapeLayer.strokeColor = UIColor.hexString("#93C6EC").cgColor +// shapeLayer.fillColor = UIColor.clear.cgColor +// shapeLayer.lineWidth = lineWidth +// shapeLayer.lineDashPattern = [NSNumber(value: dashLength), NSNumber(value: spaceLength)] +// layer.addSublayer(shapeLayer) +// } } diff --git a/ShenYin/ShenYin/UI/common/LoadingButton.swift b/ShenYin/ShenYin/UI/common/LoadingButton.swift index 8bec230..7565b2b 100644 --- a/ShenYin/ShenYin/UI/common/LoadingButton.swift +++ b/ShenYin/ShenYin/UI/common/LoadingButton.swift @@ -26,7 +26,7 @@ class LoadingButton:UIButton{ loading = true activeView.backgroundColor = .hexString("#F7F7F7") activeView.startAnimating() - DispatchQueue.main.asyncAfter(deadline:.now() + 3) { + DispatchQueue.main.asyncAfter(deadline:.now() + 2) { self.stopAnimating() finished?() } @@ -88,29 +88,43 @@ class RecordingView: UIView { activeView.stopAnimating() } } -class RecordingButton:UIButton{ - let activeView = DGActivityIndicatorView(type: .lineScalePulseOut,tintColor: UIColor.hexString("#0092E1"))! +class DialogRecordingButton:UIButton{ + let activeView = DGActivityIndicatorView(type: .lineScalePulseOut,tintColor: UIColor.hexString("#919191"),size: 20)! + let loadView = DGActivityIndicatorView(type: .ballClipRotate,tintColor: UIColor.hexString("#919191"))! override init(frame: CGRect) { super.init(frame: frame) activeView.backgroundColor = .hexString("#F7F7F7") + activeView.yc.setBorder(width: 2, color: .hexString("#919191"), radius: 17) addSubview(activeView) activeView.snp.remakeConstraints { make in make.edges.equalToSuperview() } + + addSubview(loadView) + loadView.snp.remakeConstraints { make in + make.edges.equalToSuperview() + } + loadView.backgroundColor = .hexString("#F7F7F7") } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func startAnimating(finished:(()->Void)? = nil){ + loadView.isHidden = true + activeView.isHidden = false activeView.startAnimating() -// DispatchQueue.main.asyncAfter(deadline:.now() + 3) { -// self.stopAnimating() -// finished?() -// } } - func stopAnimating(){ + func stopAnimating(finished:@escaping (()->Void)){ activeView.stopAnimating() + activeView.isHidden = true + + loadView.isHidden = false + loadView.startAnimating() + DispatchQueue.main.asyncAfter(deadline:.now() + 2) { [weak self] in + self?.loadView.stopAnimating() + finished() + } } } diff --git a/ShenYin/ShenYin/UI/common/NotificationManager.swift b/ShenYin/ShenYin/UI/common/NotificationManager.swift new file mode 100644 index 0000000..50771da --- /dev/null +++ b/ShenYin/ShenYin/UI/common/NotificationManager.swift @@ -0,0 +1,38 @@ +// +// Untitled.swift +// ShenYin +// +// Created by liangshi on 2025/9/26. +// + +import Foundation + +enum NotificationType:String{ + case deviceValidChange + + var value:String{ + switch self { + case .deviceValidChange: + return "deviceValidChange" + default: + return "unknown" + } + } +} + + +class NotificationManager { + static func add(_ observer: Any, selector aSelector: Selector, forName name: NotificationType) { + NotificationCenter.default.addObserver(observer, selector: aSelector, name: Notification.Name(name.value), object: nil) + } + + static func post(type:NotificationType,objtect:Any?){ + NotificationCenter.default.post(name: Notification.Name(type.value), object: objtect, userInfo:nil) + } + + @objc func handleNotification(_ notification: Notification) { + if let data = notification.userInfo?["data"] as? String { + print("Received data: \(data)") + } + } +}