@@ -40,13 +40,37 @@ class StationsViewController: BaseController, Handoffable {
4040 return controller
4141 } ( )
4242
43- private let animationView : NVActivityIndicatorView = {
44- let activityIndicatorView = NVActivityIndicatorView ( frame: . zero, type: . audioEqualizer, color: . white, padding: nil )
43+ private var isBuffering = false
44+
45+ private let equalizerView : NVActivityIndicatorView = {
46+ let view = NVActivityIndicatorView ( frame: . zero, type: . audioEqualizer, color: . white, padding: nil )
47+ view. translatesAutoresizingMaskIntoConstraints = false
48+ return view
49+ } ( )
50+
51+ private let bufferingView : NVActivityIndicatorView = {
52+ let view = NVActivityIndicatorView ( frame: . zero, type: . ballPulse, color: . white, padding: nil )
53+ view. translatesAutoresizingMaskIntoConstraints = false
54+ return view
55+ } ( )
56+
57+ private lazy var nowPlayingIndicator : UIView = {
58+ let container = UIView ( )
59+ container. addSubview ( equalizerView)
60+ container. addSubview ( bufferingView)
4561 NSLayoutConstraint . activate ( [
46- activityIndicatorView. widthAnchor. constraint ( equalToConstant: 30 ) ,
47- activityIndicatorView. heightAnchor. constraint ( equalToConstant: 20 )
62+ container. widthAnchor. constraint ( equalToConstant: 30 ) ,
63+ container. heightAnchor. constraint ( equalToConstant: 20 ) ,
64+ equalizerView. centerXAnchor. constraint ( equalTo: container. centerXAnchor) ,
65+ equalizerView. centerYAnchor. constraint ( equalTo: container. centerYAnchor) ,
66+ equalizerView. widthAnchor. constraint ( equalTo: container. widthAnchor) ,
67+ equalizerView. heightAnchor. constraint ( equalTo: container. heightAnchor) ,
68+ bufferingView. centerXAnchor. constraint ( equalTo: container. centerXAnchor) ,
69+ bufferingView. centerYAnchor. constraint ( equalTo: container. centerYAnchor) ,
70+ bufferingView. widthAnchor. constraint ( equalTo: container. widthAnchor) ,
71+ bufferingView. heightAnchor. constraint ( equalTo: container. heightAnchor) ,
4872 ] )
49- return activityIndicatorView
73+ return container
5074 } ( )
5175
5276 private lazy var tableView : UITableView = {
@@ -114,20 +138,45 @@ class StationsViewController: BaseController, Handoffable {
114138 }
115139
116140 guard navigationItem. rightBarButtonItem == nil else { return }
117- let barButton = UIBarButtonItem ( customView: animationView )
141+ let barButton = UIBarButtonItem ( customView: nowPlayingIndicator )
118142 barButton. target = self
119143 barButton. action = #selector( nowPlayingBarButtonPressed)
120144
121145 let tapGesture = UITapGestureRecognizer ( target: self , action: #selector( nowPlayingBarButtonPressed) )
122- animationView . addGestureRecognizer ( tapGesture)
123- animationView . isUserInteractionEnabled = true
146+ nowPlayingIndicator . addGestureRecognizer ( tapGesture)
147+ nowPlayingIndicator . isUserInteractionEnabled = true
124148
125149 navigationItem. rightBarButtonItem = barButton
126- startNowPlayingAnimation ( player . isPlaying )
150+ updateNowPlayingAnimation ( )
127151 }
128152
129- private func startNowPlayingAnimation( _ animate: Bool ) {
130- animate ? animationView. startAnimating ( ) : animationView. stopAnimating ( )
153+ private func updateNowPlayingAnimation( ) {
154+ if isBuffering {
155+ equalizerView. stopAnimating ( )
156+ bufferingView. startAnimating ( )
157+ } else if player. isPlaying {
158+ bufferingView. stopAnimating ( )
159+ equalizerView. startAnimating ( )
160+ } else {
161+ equalizerView. stopAnimating ( )
162+ bufferingView. stopAnimating ( )
163+ }
164+ }
165+
166+ private func updateVisibleCellsNowPlaying( ) {
167+ if !Thread. isMainThread {
168+ DispatchQueue . main. async { [ weak self] in
169+ self ? . updateVisibleCellsNowPlaying ( )
170+ }
171+ return
172+ }
173+
174+ for case let cell as StationTableViewCell in tableView. visibleCells {
175+ guard let indexPath = tableView. indexPath ( for: cell) else { continue }
176+ let station = searchController. isActive ? manager. searchedStations [ indexPath. row] : manager. stations [ indexPath. row]
177+ let isCurrentStation = station == manager. currentStation
178+ cell. setNowPlaying ( isPlaying: player. isPlaying, isBuffering: isBuffering, isCurrentStation: isCurrentStation)
179+ }
131180 }
132181
133182 @objc private func nowPlayingBarButtonPressed( ) {
@@ -162,7 +211,7 @@ class StationsViewController: BaseController, Handoffable {
162211extension StationsViewController : UITableViewDataSource {
163212
164213 func tableView( _ tableView: UITableView , heightForRowAt indexPath: IndexPath ) -> CGFloat {
165- 100 .0
214+ 104 .0
166215 }
167216
168217 func numberOfSections( in tableView: UITableView ) -> Int {
@@ -189,7 +238,8 @@ extension StationsViewController: UITableViewDataSource {
189238
190239 let station = searchController. isActive ? manager. searchedStations [ indexPath. row] : manager. stations [ indexPath. row]
191240 cell. configureStationCell ( station: station)
192- cell. setNowPlaying ( isPlaying: player. isPlaying, isCurrentStation: station == manager. currentStation)
241+ let isCurrentStation = station == manager. currentStation
242+ cell. setNowPlaying ( isPlaying: player. isPlaying, isBuffering: isBuffering, isCurrentStation: isCurrentStation)
193243 return cell
194244 }
195245 }
@@ -232,9 +282,22 @@ extension StationsViewController: UISearchResultsUpdating {
232282
233283extension StationsViewController : FRadioPlayerObserver {
234284
285+ func radioPlayer( _ player: FRadioPlayer , playerStateDidChange state: FRadioPlayer . State ) {
286+ switch state {
287+ case . loading:
288+ isBuffering = true
289+ case . readyToPlay, . loadingFinished, . error:
290+ isBuffering = false
291+ default :
292+ break
293+ }
294+ updateNowPlayingAnimation ( )
295+ updateVisibleCellsNowPlaying ( )
296+ }
297+
235298 func radioPlayer( _ player: FRadioPlayer , playbackStateDidChange state: FRadioPlayer . PlaybackState ) {
236- startNowPlayingAnimation ( player . isPlaying )
237- tableView . reloadData ( )
299+ updateNowPlayingAnimation ( )
300+ updateVisibleCellsNowPlaying ( )
238301 }
239302
240303 func radioPlayer( _ player: FRadioPlayer , metadataDidChange metadata: FRadioPlayer . Metadata ? ) {
@@ -249,7 +312,7 @@ extension StationsViewController: StationsManagerObserver {
249312 }
250313
251314 func stationsManager( _ manager: StationsManager , stationDidChange station: RadioStation ? ) {
315+ updateVisibleCellsNowPlaying ( )
252316 updateNowPlayingBarButton ( station: station)
253- tableView. reloadData ( )
254317 }
255318}
0 commit comments