123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- //
- // SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- // SPDX-License-Identifier: GPL-3.0-or-later
- //
- import UIKit
- protocol AudioPlayerViewDelegate: AnyObject {
- func audioPlayerPlayButtonPressed()
- func audioPlayerPauseButtonPressed()
- func audioPlayerProgressChanged(progress: CGFloat)
- }
- class AudioPlayerView: UIView {
- @IBOutlet var contentView: UIView!
- @IBOutlet weak var playPauseButton: UIButton!
- @IBOutlet weak var slider: UISlider!
- @IBOutlet weak var durationLabel: UILabel!
- var isPlaying: Bool = false
- public weak var delegate: AudioPlayerViewDelegate?
- override init(frame: CGRect) {
- super.init(frame: frame)
- commonInit()
- }
- required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- commonInit()
- }
- func commonInit() {
- Bundle.main.loadNibNamed("AudioPlayerView", owner: self, options: nil)
- contentView.frame = self.bounds
- contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
- // Play/Pause button
- playPauseButton.addAction(for: .touchUpInside) { [unowned self] in
- if isPlaying {
- delegate?.audioPlayerPauseButtonPressed()
- } else {
- delegate?.audioPlayerPlayButtonPressed()
- }
- }
- // Slider
- let thumbImage = UIImage(systemName: "circle.fill")?
- .withConfiguration(UIImage.SymbolConfiguration(pointSize: 16))
- .withTintColor(.label, renderingMode: .alwaysOriginal)
- slider.setThumbImage(thumbImage, for: .normal)
- slider.semanticContentAttribute = .forceLeftToRight
- slider.addAction(for: .valueChanged) { [unowned self] in
- delegate?.audioPlayerProgressChanged(progress: CGFloat(slider.value))
- }
- // Duration label
- hideDurationLabel()
- backgroundColor = .secondarySystemBackground
- layer.cornerRadius = 8.0
- layer.masksToBounds = true
- self.addSubview(contentView)
- }
- func setPlayerProgress(_ progress: CGFloat, isPlaying playing: Bool, maximumValue maxValue: CGFloat) {
- setPlayPauseButton(playing: playing)
- slider.isEnabled = true
- slider.value = Float(progress)
- slider.maximumValue = Float(maxValue)
- setDurationLabel(progress: progress, duration: maxValue)
- slider.setNeedsLayout()
- }
- func resetPlayer() {
- setPlayPauseButton(playing: false)
- slider.isEnabled = false
- slider.value = 0
- hideDurationLabel()
- slider.setNeedsLayout()
- }
- func setPlayPauseButton(playing: Bool) {
- isPlaying = playing
- if isPlaying {
- playPauseButton.setImage(UIImage(systemName: "pause.fill"), for: .normal)
- } else {
- playPauseButton.setImage(UIImage(systemName: "play.fill"), for: .normal)
- }
- }
- func setDurationLabel(progress: CGFloat, duration: CGFloat) {
- let dateComponentsFormatter = DateComponentsFormatter()
- dateComponentsFormatter.allowedUnits = [.minute, .second]
- dateComponentsFormatter.zeroFormattingBehavior = []
- let progressTime = dateComponentsFormatter.string(from: TimeInterval(progress)) ?? "0:00"
- let durationTime = dateComponentsFormatter.string(from: TimeInterval(duration)) ?? "0:00"
- let playerTimeString = "\(progressTime)".withTextColor(.label).withFont(.systemFont(ofSize: 13, weight: .medium))
- playerTimeString.append(" / \(durationTime)".withTextColor(.secondaryLabel).withFont(.systemFont(ofSize: 13)))
- durationLabel.attributedText = playerTimeString
- }
- func hideDurationLabel() {
- durationLabel.text = ""
- }
- }
|