[Lofi Time Radio App] Station Presentation — (Part 6)

Cuu Long Hoang
4 min readMar 10, 2023

--

Hi, I want to show you the Presentation layer to continue this series. If you are the first time read my blog, please read the introduction post. In MVP Architecture, the Presentation layer is the gear of the architecture to connect the Model and View. The Presentation will let the View know which part needs to show on the screen.

I. LoadingView and LoadingViewModel:

LoadingView describes the loading state of the view.

public protocol LoadingView {
func display(_ viewModel: LoadingViewModel)
}

LoadingViewModel describes the state of loading.

public struct LoadingViewModel {
public let isLoading: Bool

public init(isLoading: Bool) {
self.isLoading = isLoading
}
}

II. SongView and SongViewModel:

SongView describes the playing song to the view.

public protocol SongView {
func display(_ viewModel: SongViewModel)
}

SongViewModel describes the information of the playing song such as name, artist, and image URL.

public struct SongViewModel {
public let imageURL: URL
public let name: String
public let artist: String

public init(imageURL: URL, name: String, artist: String) {
self.imageURL = imageURL
self.name = name
self.artist = artist
}
}

III. AudienceView and AudienceViewModel:

AudienceView describes the audience listening to the playing song.

public protocol AudienceView {
func display(_ viewModel: AudienceViewModel)
}

AudienceViewModel describes the number of audiences listening to the playing song.

public struct AudienceViewModel {
public var total: Int

public init(total: Int) {
self.total = total
}
}

IV. RuntimeView and RuntimeViewModel:

RuntimeView describes the run time of the playing song.

public protocol RuntimeView {
func display(_ viewModel: RunTimeViewModel)
}

RuntimeViewModel describes the information of the playing song run time such as duration, elapsed, remaining, elapsedSeconds, requestNextSong.

public struct RunTimeViewModel {
public let elapsed: String // 00:30
public let remaining: String // 01:00
public let duration: Int // 180
public let elapsedSeconds: Int // 30
public let requestNextSong: Bool // inform view request next song infor

public init(elapsed: String,
remaining: String,
duration: Int,
elapsedSeconds: Int,
requestNextSong: Bool) {
self.elapsed = elapsed
self.remaining = remaining
self.duration = duration
self.elapsedSeconds = elapsedSeconds
self.requestNextSong = requestNextSong
}
}

V. ControlView and ControlViewModel:

ControlView describes the state of the play/pause button in the view.

public protocol ControlView {
func display(_ viewModel: ControlViewModel)
}

ControlViewModel describes the audio state information, ex: resumed, paused…

public enum AudioState: Hashable {
case resumed
case paused
}

public struct ControlViewModel {
public let state: AudioState

public init(state: AudioState) {
self.state = state
}

public static var resumed: ControlViewModel {
return ControlViewModel(state: .resumed)
}

public static var paused: ControlViewModel {
return ControlViewModel(state: .paused)
}
}

VI. ErrorView and ErrorViewModel:

ErrorView describes the error state of the view.

public protocol ErrorView {
func display(_ viewModel: ErrorViewModel)
}

ErrorViewModel describes the error message when something wrong happens.

public struct ErrorViewModel: Equatable {
public let message: String?

public static var noError: ErrorViewModel {
return ErrorViewModel(message: nil)
}

public static func error(message: String) -> ErrorViewModel {
return ErrorViewModel(message: message)
}
}

That’s all for this post. In the next post, I will show you how I apply TDD to create the RadioPresenter for using all View Protocols mentioned above.

Thank you for reading! See ya!

--

--

Cuu Long Hoang
Cuu Long Hoang

No responses yet