@@ -25,13 +25,27 @@ class NowPlayingViewController: UIViewController {
2525
2626 // MARK: - UI
2727 private let backgroundImageView : UIImageView = {
28- let image = UIImage ( named: " background " )
29- let imageView = UIImageView ( image: image)
28+ let imageView = UIImageView ( )
3029 imageView. contentMode = . scaleAspectFill
30+ imageView. clipsToBounds = true
3131 imageView. translatesAutoresizingMaskIntoConstraints = false
3232 return imageView
3333 } ( )
3434
35+ private let backgroundBlurView : UIVisualEffectView = {
36+ let blur = UIBlurEffect ( style: . systemThickMaterialDark)
37+ let view = UIVisualEffectView ( effect: blur)
38+ view. translatesAutoresizingMaskIntoConstraints = false
39+ return view
40+ } ( )
41+
42+ private let backgroundDimView : UIView = {
43+ let view = UIView ( )
44+ view. backgroundColor = UIColor . black. withAlphaComponent ( 0.3 )
45+ view. translatesAutoresizingMaskIntoConstraints = false
46+ return view
47+ } ( )
48+
3549 private let albumArtworkView = AlbumArtworkView ( )
3650 private let controlsView = ControlsView ( )
3751 private var topConstraint : NSLayoutConstraint ?
@@ -65,19 +79,21 @@ class NowPlayingViewController: UIViewController {
6579
6680 override func viewDidLayoutSubviews( ) {
6781 super. viewDidLayoutSubviews ( )
68- topConstraint? . constant = navigationController != nil ? 8 : 40
82+ topConstraint? . constant = navigationController != nil ? 16 : 48
6983 }
7084
7185 private func isPlayingDidChange( _ isPlaying: Bool ) {
7286 controlsView. setPlaying ( isPlaying)
73- controlsView . setStop ( isPlaying)
87+ albumArtworkView . setPlaying ( isPlaying)
7488 updatePopupBarPlayPauseButton ( isPlaying: isPlaying)
7589 }
7690
7791 func stationDidChange( ) {
7892 albumArtworkView. setImage ( nil )
93+ updateBackground ( with: nil )
7994 manager. currentStation? . getImage { [ weak self] image in
8095 self ? . albumArtworkView. setImage ( image)
96+ self ? . updateBackground ( with: image)
8197 self ? . updatePopupBarImage ( image)
8298 }
8399
@@ -86,78 +102,63 @@ class NowPlayingViewController: UIViewController {
86102 controlsView. setLive ( player. duration == 0 )
87103 }
88104
89- func updateLabels( with statusMessage: String ? = nil , animate: Bool = true ) {
90- guard let statusMessage = statusMessage else {
91- controlsView. updateLabels ( with: . track( song: manager. currentStation? . trackName,
92- artist: manager. currentStation? . artistName) )
93- return
94- }
95-
96- controlsView. updateLabels ( with: . status( message: statusMessage, name: manager. currentStation? . name) )
105+ func updateLabels( ) {
106+ controlsView. updateNowPlaying (
107+ song: player. currentMetadata? . trackName,
108+ artist: player. currentMetadata? . artistName,
109+ stationName: manager. currentStation? . name,
110+ stationDesc: manager. currentStation? . desc
111+ )
97112 }
98113
99- func playbackStateDidChange( _ playbackState: FRadioPlayer . PlaybackState , animate: Bool ) {
100-
101- let message : String ?
102-
103- switch playbackState {
104- case . paused:
105- message = " Paused... "
106- case . playing:
107- message = nil
108- case . stopped:
109- message = " Stopped... "
110- }
111-
112- updateLabels ( with: message, animate: animate)
114+ func playbackStateDidChange( _ playbackState: FRadioPlayer . PlaybackState ) {
113115 isPlayingDidChange ( player. isPlaying)
114116 }
115117
116- func playerStateDidChange( _ state: FRadioPlayer . State , animate: Bool ) {
117-
118- let message : String ?
119-
118+ func playerStateDidChange( _ state: FRadioPlayer . State ) {
120119 switch state {
121- case . loading:
122- message = " Loading ... "
123- case . urlNotSet:
124- message = " URL not valide "
125120 case . readyToPlay, . loadingFinished:
126- playbackStateDidChange ( player. playbackState, animate: animate)
127- return
128- case . error:
129- message = " Error Playing "
121+ playbackStateDidChange ( player. playbackState)
122+ default :
123+ break
130124 }
131-
132- updateLabels ( with: message, animate: animate)
133125 }
134126
135127 // MARK: - Setup Methods
136128
137129 private func setupViews( ) {
130+ // Dynamic blurred background
138131 view. addSubview ( backgroundImageView)
132+ view. addSubview ( backgroundBlurView)
133+ view. addSubview ( backgroundDimView)
139134
140135 NSLayoutConstraint . activate ( [
141136 backgroundImageView. topAnchor. constraint ( equalTo: view. topAnchor) ,
142- backgroundImageView. rightAnchor. constraint ( equalTo: view. rightAnchor) ,
137+ backgroundImageView. leadingAnchor. constraint ( equalTo: view. leadingAnchor) ,
138+ backgroundImageView. trailingAnchor. constraint ( equalTo: view. trailingAnchor) ,
143139 backgroundImageView. bottomAnchor. constraint ( equalTo: view. bottomAnchor) ,
144- backgroundImageView. leftAnchor. constraint ( equalTo: view. leftAnchor)
140+
141+ backgroundBlurView. topAnchor. constraint ( equalTo: view. topAnchor) ,
142+ backgroundBlurView. leadingAnchor. constraint ( equalTo: view. leadingAnchor) ,
143+ backgroundBlurView. trailingAnchor. constraint ( equalTo: view. trailingAnchor) ,
144+ backgroundBlurView. bottomAnchor. constraint ( equalTo: view. bottomAnchor) ,
145+
146+ backgroundDimView. topAnchor. constraint ( equalTo: view. topAnchor) ,
147+ backgroundDimView. leadingAnchor. constraint ( equalTo: view. leadingAnchor) ,
148+ backgroundDimView. trailingAnchor. constraint ( equalTo: view. trailingAnchor) ,
149+ backgroundDimView. bottomAnchor. constraint ( equalTo: view. bottomAnchor) ,
145150 ] )
146151
147152 let mainStackView = UIStackView ( arrangedSubviews: [ albumArtworkView, controlsView] )
148153 mainStackView. axis = . vertical
149- mainStackView. spacing = 20
150- mainStackView. distribution = . fillEqually
154+ mainStackView. spacing = 24
155+ mainStackView. distribution = . fill
151156 mainStackView. translatesAutoresizingMaskIntoConstraints = false
152157
153158 controlsView. playingAction = { [ unowned self] in
154159 player. togglePlaying ( )
155160 }
156161
157- controlsView. stopAction = { [ unowned self] in
158- player. stop ( )
159- }
160-
161162 controlsView. nextAction = { [ unowned self] in
162163 manager. setNext ( )
163164 }
@@ -166,10 +167,6 @@ class NowPlayingViewController: UIViewController {
166167 manager. setPrevious ( )
167168 }
168169
169- controlsView. logoAction = { [ unowned self] in
170- delegate? . didTapCompanyButton ( self )
171- }
172-
173170 controlsView. moreAction = { [ unowned self] in
174171 handleMoreMenu ( )
175172 }
@@ -182,34 +179,50 @@ class NowPlayingViewController: UIViewController {
182179
183180 topConstraint = mainStackView. topAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. topAnchor, constant: 8 )
184181
182+ let artworkHeight = albumArtworkView. heightAnchor. constraint ( equalTo: mainStackView. heightAnchor, multiplier: 0.55 )
183+ artworkHeight. priority = . defaultHigh
184+
185185 NSLayoutConstraint . activate ( [
186186 topConstraint!,
187- mainStackView. leadingAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. leadingAnchor, constant: 20 ) ,
188- mainStackView. trailingAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. trailingAnchor, constant: - 20 ) ,
189- mainStackView. bottomAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. bottomAnchor, constant: - 20 )
187+ mainStackView. leadingAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. leadingAnchor, constant: 24 ) ,
188+ mainStackView. trailingAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. trailingAnchor, constant: - 24 ) ,
189+ mainStackView. bottomAnchor. constraint ( equalTo: view. safeAreaLayoutGuide. bottomAnchor, constant: - 20 ) ,
190+ artworkHeight,
190191 ] )
191192 }
192193
194+ // MARK: - Dynamic Background
195+
196+ private func updateBackground( with image: UIImage ? ) {
197+ UIView . transition (
198+ with: backgroundImageView,
199+ duration: 0.5 ,
200+ options: . transitionCrossDissolve
201+ ) {
202+ self . backgroundImageView. image = image
203+ }
204+ }
205+
193206 func updateTrackArtwork( ) {
194- getTrackArtwork { [ weak self] image, isAnimated in
207+ getTrackArtwork { [ weak self] image in
195208 DispatchQueue . main. async {
196- self ? . albumArtworkView. setImage ( image)
197- if isAnimated { self ? . albumArtworkView . animate ( ) }
209+ self ? . albumArtworkView. setImage ( image, animated : true )
210+ self ? . updateBackground ( with : image )
198211 self ? . updatePopupBarImage ( image)
199212 }
200213 }
201214 }
202215
203- private func getTrackArtwork( completion: @escaping ( UIImage ? , Bool ) -> Void ) {
216+ private func getTrackArtwork( completion: @escaping ( UIImage ? ) -> Void ) {
204217 guard let artworkURL = player. currentArtworkURL else {
205218 manager. currentStation? . getImage { image in
206- completion ( image, false )
219+ completion ( image)
207220 }
208221 return
209222 }
210223
211224 UIImage . image ( from: artworkURL) { image in
212- completion ( image, true )
225+ completion ( image)
213226 }
214227 }
215228
@@ -273,11 +286,11 @@ class NowPlayingViewController: UIViewController {
273286extension NowPlayingViewController : FRadioPlayerObserver {
274287
275288 func radioPlayer( _ player: FRadioPlayer , playerStateDidChange state: FRadioPlayer . State ) {
276- playerStateDidChange ( state, animate : true )
289+ playerStateDidChange ( state)
277290 }
278291
279292 func radioPlayer( _ player: FRadioPlayer , playbackStateDidChange state: FRadioPlayer . PlaybackState ) {
280- playbackStateDidChange ( state, animate : true )
293+ playbackStateDidChange ( state)
281294 }
282295
283296 func radioPlayer( _ player: FRadioPlayer , metadataDidChange metadata: FRadioPlayer . Metadata ? ) {
@@ -317,7 +330,7 @@ extension NowPlayingViewController: BottomSheetViewControllerDelegate {
317330
318331 func bottomSheet( _ controller: BottomSheetViewController , didSelect option: BottomSheetViewController . Option ) {
319332 if case . share = option {
320- getTrackArtwork { [ weak self] image, _ in
333+ getTrackArtwork { [ weak self] image in
321334 guard let self = self else { return }
322335 self . delegate? . didSelectBottomSheetOption ( . share( image) , from: self )
323336 }
0 commit comments