LNSkillVoiceBarView.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //
  2. // LNSkillVoiceBarView.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/11/30.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. class LNSkillVoiceBarView: UIView {
  11. private let durationLabel = UILabel()
  12. private var curUrl: String?
  13. private let playStateIc = UIImageView()
  14. private let voiceWaveView = LNVoiceWaveView()
  15. override init(frame: CGRect) {
  16. super.init(frame: frame)
  17. setupViews()
  18. LNEventDeliver.addObserver(self)
  19. }
  20. func setVoice(_ url: String) {
  21. curUrl = url
  22. LNVoiceResourceManager.shared.getRemoteAudioDuration(urlStr: url)
  23. { [weak self] duration, err in
  24. guard let self else { return }
  25. guard let duration, err == nil else { return }
  26. guard curUrl == url else { return }
  27. isHidden = duration <= 0
  28. durationLabel.text = "\(Int(duration.rounded()))\""
  29. }
  30. }
  31. required init?(coder: NSCoder) {
  32. fatalError("init(coder:) has not been implemented")
  33. }
  34. }
  35. extension LNSkillVoiceBarView: LNVoicePlayerNotify {
  36. func onAudioStartPlay(path: String) {
  37. guard path == curUrl else { return }
  38. playStateIc.image = .icVoicePause
  39. voiceWaveView.startAnimate()
  40. }
  41. func onAudioStopPlay(path: String) {
  42. guard path == curUrl else { return }
  43. playStateIc.image = .icVoicePlay
  44. voiceWaveView.stopAnimate()
  45. LNVoiceResourceManager.shared.getRemoteAudioDuration(urlStr: path)
  46. { [weak self] duration, err in
  47. guard let self else { return }
  48. guard let duration, err == nil else { return }
  49. guard curUrl == path else { return }
  50. isHidden = duration <= 0
  51. durationLabel.text = "\(Int(duration.rounded()))\""
  52. }
  53. }
  54. func onAudioUpdateDuration(path: String, cur: TimeInterval, total: TimeInterval) {
  55. guard path == curUrl else { return }
  56. durationLabel.text = "\(Int((total - cur).rounded()))\""
  57. }
  58. }
  59. extension LNSkillVoiceBarView {
  60. private func setupViews() {
  61. isHidden = true
  62. snp.makeConstraints { make in
  63. make.width.equalTo(86)
  64. make.height.equalTo(31)
  65. }
  66. let button = UIButton()
  67. button.setBackgroundImage(.primary_7, for: .normal)
  68. button.layer.cornerRadius = 15.5
  69. button.clipsToBounds = true
  70. button.addAction(UIAction(handler: { [weak self] _ in
  71. guard let self else { return }
  72. guard let curUrl else { return }
  73. if LNVoicePlayer.shared.playingUrl == curUrl {
  74. LNVoicePlayer.shared.stop()
  75. } else {
  76. LNVoicePlayer.shared.play(curUrl)
  77. }
  78. }), for: .touchUpInside)
  79. addSubview(button)
  80. button.snp.makeConstraints { make in
  81. make.edges.equalToSuperview()
  82. }
  83. playStateIc.image = .icVoicePlay
  84. addSubview(playStateIc)
  85. playStateIc.snp.makeConstraints { make in
  86. make.leading.equalToSuperview().offset(8)
  87. make.centerY.equalToSuperview()
  88. make.width.height.equalTo(22)
  89. }
  90. voiceWaveView.build()
  91. voiceWaveView.isUserInteractionEnabled = false
  92. addSubview(voiceWaveView)
  93. voiceWaveView.snp.makeConstraints { make in
  94. make.centerY.equalToSuperview()
  95. make.leading.equalTo(playStateIc.snp.trailing).offset(5)
  96. make.width.equalTo(18.5)
  97. make.height.equalTo(11)
  98. }
  99. durationLabel.font = .heading_h5
  100. durationLabel.textColor = .text_1
  101. durationLabel.textAlignment = .center
  102. addSubview(durationLabel)
  103. durationLabel.snp.makeConstraints { make in
  104. make.leading.equalTo(voiceWaveView.snp.trailing).offset(4)
  105. make.centerY.equalToSuperview()
  106. make.trailing.equalToSuperview().offset(-7)
  107. }
  108. }
  109. }