--- /dev/null
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "lvdong@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
--- /dev/null
+{
+ "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
+ }
+}
--- /dev/null
+{
+ "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
+ }
+}
--- /dev/null
+{
+ "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
+ }
+}
--- /dev/null
+{
+ "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
+ }
+}
--- /dev/null
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "语音发送中@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "语音发送中@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
+++ /dev/null
-//
-// 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))
-}
--- /dev/null
+//
+// 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)
+ }
+}
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
}
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{
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}
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
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() {
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
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
}
}
}
}
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)
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 {
valueLabel.do { v in
v.textColor = .rgb(0x666666)
v.font = .regular(10)
- v.text = "耳机"
}
}
--- /dev/null
+//
+// 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()
+ }
+ }
+}
let toolBar = DialogRecordBar()
var recordFilePath : String?
+ let splitView = DialogSplitView()
let tableView = UITableView(frame: CGRectZero, style: .plain)
var dataList:[DialogTranslateCellModel] = []
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")
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)
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
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(){
if dataList.count > 0 {
tableView.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true)
}
+ splitView.dataList = dataList
}
}
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) {
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()
}
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 {
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) {
///监听到一句话结束,自动结束当前录音
if (model.definite == true) {
+ toolBar.stopRecord(.phone)
stopPhoneRecord()
}
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) {
///监听到一句话结束,自动结束当前录音
if (model.definite == true) {
+ toolBar.stopRecord(.earphone)
stopEarRecord()
}
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
}
}
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")
}
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)
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)
}
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(){
--- /dev/null
+//
+// Untitled.swift
+// ShenYin
+//
+// Created by liangshi on 2025/9/25.
+//
+
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
}
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{
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}
//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()
+ }
}
var y = 0.0
for (index, value) in list.enumerated() {
let view = HomeCell()
+ view.enable = App.shared.deviceValid
addSubview(view)
view.type = value
}
}
}
+ 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 {
icon.image = UIImage(named: type.icon)
}
}
+ var enable:Bool = false{
+ didSet{
+ if enable {
+ alpha = 1
+ }
+ else{
+ alpha = 0.3
+ }
+ }
+ }
override func setupViews() {
addSubview(bgView)
}
}
@objc func tapAction(){
+ if !App.shared.deviceValid {
+ return
+ }
switch type {
case .fileRecord:
App.shared.goToPage(FieldRecordingVC())
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])
v.font = .regular(14)
v.text = "随时随地 一键开录"
}
+ self.enable = App.shared.deviceValid
+ NotificationManager.add(self, selector: #selector(deviceChange(_:)), forName: .deviceValidChange)
}
override func setupLayout() {
}
}
@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
}
}
}
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
import UIKit
import IQKeyboardManagerSwift
-
class AppLaunch:NSObject{
@MainActor static func start(){
JoySdkManager.shared.setupSdk()
static let shared = App()
var window:UIWindow?
-
func topVC()->UIViewController!{
guard let vc = window?.rootViewController else{
Logger.debug("页面异常!!!")
}
}
}
+
+extension App{
+ var deviceValid:Bool{
+ return BleManager.shared.isConnetd
+ }
+}
}
static let shared = BleManager()
+ var isConnetd:Bool = false
func setupJoySdk(){
JoyGemAIManager.shared().delegate = self;
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
Logger.debug("蓝牙已断开 \(peripheral)")
+ self.isConnetd = false
+ NotificationManager.post(type: .deviceValidChange, objtect: nil)
disConnectDeviceCallback?(peripheral)
+ checkConnect()
}
}
}
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 {
//MARK: 使能成功时需要
Logger.debug("特征使能成功")
JoyGemAIManager.shared().bleConnected()
+
}
}
func connectPeripheral(_ peripheral: CBPeripheral) {
Logger.debug("连接中...")
centralManager.connect(peripheral, options: [CBConnectPeripheralOptionEnableTransportBridgingKey:true])
- YLprogressHUD.showLoading()
}
func cancel() {
}
func joyGemAuthSuccessCallback() {
+ self.isConnetd = true
+ NotificationManager.post(type: .deviceValidChange, objtect: nil)
ConnectPopView().showAutoHide {
App.shared.enter()
}
//
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)
+// }
}
loading = true
activeView.backgroundColor = .hexString("#F7F7F7")
activeView.startAnimating()
- DispatchQueue.main.asyncAfter(deadline:.now() + 3) {
+ DispatchQueue.main.asyncAfter(deadline:.now() + 2) {
self.stopAnimating()
finished?()
}
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()
+ }
}
}
--- /dev/null
+//
+// 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)")
+ }
+ }
+}