LNVoicePlayView.swift 3.3 KB

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