Skip to content

Commit

Permalink
feat(artist): fix loader
Browse files Browse the repository at this point in the history
  • Loading branch information
angristan committed Jul 19, 2021
1 parent 90c5047 commit ed46f91
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 105 deletions.
38 changes: 29 additions & 9 deletions firstfm/ViewModel/ArtistViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,38 @@ class ArtistViewModel: ObservableObject {
@Published var albums: [ArtistAlbum] = []
@Published var tracks: [Track] = []
@Published var artist: ArtistInfo?
var isAlbumsLoading = true
var isTracksLoading = true
var isInfoLoading = true

var isLoading = true

func reset() {
self.isLoading = true
self.isAlbumsLoading = true
self.isTracksLoading = true
self.isInfoLoading = true
}

func getArtistAlbums(_ artistName: String) {
func setIsLoading() {
if !isAlbumsLoading && !isTracksLoading && !isInfoLoading {
self.isLoading = false
}
}

func getAll(_ artist: Artist) {
reset()

self.getArtistAlbums(artist.name)
self.getArtistTracks(artist.name)
self.getArtistInfo(artist.name)
}

func getArtistAlbums(_ artistName: String) {
LastFMAPI.request(lastFMMethod: "artist.getTopAlbums", args: [
"limit": "6",
"artist": artistName
]) { (data: ArtistTopAlbumsResponse?, error) -> Void in
self.isLoading = false

if error != nil {
DispatchQueue.main.async {
FloatingNotificationBanner(title: "Failed to load albums", subtitle: error?.localizedDescription, style: .danger).show()
Expand All @@ -37,6 +55,8 @@ class ArtistViewModel: ObservableObject {
if let data = data {
DispatchQueue.main.async {
self.albums = data.topalbums.album
self.isAlbumsLoading = false
self.setIsLoading()
}

for (index, album) in data.topalbums.album.enumerated() {
Expand All @@ -55,13 +75,11 @@ class ArtistViewModel: ObservableObject {
}

func getArtistTracks(_ artistName: String) {
reset()

LastFMAPI.request(lastFMMethod: "artist.getTopTracks", args: [
"limit": "5",
"artist": artistName
]) { (data: ArtistTopTracksResponse?, error) -> Void in
self.isLoading = false

if error != nil {
DispatchQueue.main.async {
FloatingNotificationBanner(title: "Failed to load tracks", subtitle: error?.localizedDescription, style: .danger).show()
Expand All @@ -73,6 +91,8 @@ class ArtistViewModel: ObservableObject {
if let data = data {
DispatchQueue.main.async {
self.tracks = data.toptracks.track
self.isTracksLoading = false
self.setIsLoading()
}

for (index, track) in data.toptracks.track.enumerated() {
Expand All @@ -90,12 +110,10 @@ class ArtistViewModel: ObservableObject {
}

func getArtistInfo(_ artistName: String) {
reset()

LastFMAPI.request(lastFMMethod: "artist.getInfo", args: [
"artist": artistName
]) { (data: ArtistInfoResponse?, error) -> Void in
self.isLoading = false

if error != nil {
DispatchQueue.main.async {
FloatingNotificationBanner(title: "Failed to artist info", subtitle: error?.localizedDescription, style: .danger).show()
Expand All @@ -107,6 +125,8 @@ class ArtistViewModel: ObservableObject {
if let data = data {
DispatchQueue.main.async {
self.artist = data.artist
self.isInfoLoading = false
self.setIsLoading()
}

for (index, artist) in data.artist.similar.artist.enumerated() {
Expand Down
193 changes: 97 additions & 96 deletions firstfm/Views/ArtistView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,119 +27,120 @@ struct ArtistView: View {
@State private var isPullLoaderShowing = false

var body: some View {
GeometryReader { g in
FancyScrollView(title: artist.name,
headerHeight: 350,
scrollUpHeaderBehavior: .parallax,
scrollDownHeaderBehavior: .offset,
header: {
KFImage.url(URL(string: artist.image[0].url )!)
.resizable()
.loadImmediately()
.aspectRatio(contentMode: .fill)
.overlay(TintOverlay().opacity(0.2))
}) {
VStack(alignment: .leading) {
Group {
HStack {
Text("\(Int(artist.playcount ?? "0")?.formatted() ?? "0") scrobbles")
.font(.subheadline)
.foregroundColor(.gray)
Text("\(Int(artist.listeners)?.formatted() ?? "0") listeners")
.font(.subheadline)
.foregroundColor(.gray)
}
Text(model.artist?.bio.content ?? "rip").lineLimit(3)

ScrollView(.horizontal, showsIndicators: true) {
ZStack {
GeometryReader { g in
FancyScrollView(title: artist.name,
headerHeight: 350,
scrollUpHeaderBehavior: .parallax,
scrollDownHeaderBehavior: .offset,
header: {
KFImage.url(URL(string: artist.image[0].url )!)
.resizable()
.loadImmediately()
.aspectRatio(contentMode: .fill)
.overlay(TintOverlay().opacity(0.2))
}) {
VStack(alignment: .leading) {
Group {
HStack {
if let artist = self.model.artist {
ForEach(artist.tags.tag, id: \.name) {tag in
Button(action: {}) {
HStack {
Text(tag.name)
Text("\(Int(artist.playcount ?? "0")?.formatted() ?? "0") scrobbles")
.font(.subheadline)
.foregroundColor(.gray)
Text("\(Int(artist.listeners)?.formatted() ?? "0") listeners")
.font(.subheadline)
.foregroundColor(.gray)
}
Text(model.artist?.bio.content ?? "rip").lineLimit(3)

ScrollView(.horizontal, showsIndicators: true) {
HStack {
if let artist = self.model.artist {
ForEach(artist.tags.tag, id: \.name) {tag in
Button(action: {}) {
HStack {
Text(tag.name)
}
}
.padding(10)
.foregroundColor(.white)
.background(Color.gray)
.cornerRadius(.infinity)
.lineLimit(1)
}
.padding(10)
.foregroundColor(.white)
.background(Color.gray)
.cornerRadius(.infinity)
.lineLimit(1)
}
}
}
}
}.padding()

List {
Section {
Text("Top tracks").font(.headline)
ForEach(model.tracks, id: \.name) { track in
NavigationLink(
destination: Color(.red),
label: {
TrackRow(track: track)
})
}
}
}.frame(width: g.size.width - 5, height: g.size.height * 0.7, alignment: .center)
Section {
Text("Top albums").font(.headline)
LazyVGrid(columns: [
GridItem(.flexible(minimum: 50, maximum: 200)),
GridItem(.flexible(minimum: 50, maximum: 200))
], spacing: 30 ) {
ForEach(model.albums, id: \.name) { album in
NavigationLink(
destination: Color(.red),
label: {
VStack {
KFImage.url(URL(string: album.image[0].url )!)
.resizable()
.loadImmediately()
.cornerRadius(5)
.aspectRatio(contentMode: .fill)
Text(album.name).font(.headline).lineLimit(1).foregroundColor(.white)
Text("\(String(format: "%ld", locale: Locale.current, album.playcount) ) listeners")
.font(.subheadline)
.foregroundColor(.gray).lineLimit(1)
}
})

}.padding()

List {
Section {
Text("Top tracks").font(.headline)
ForEach(model.tracks, id: \.name) { track in
NavigationLink(
destination: Color(.red),
label: {
TrackRow(track: track)
})
}
}
}
}.padding().offset(y: -50)

Section {
Text("Similar artists").font(.headline)
ScrollView(.horizontal, showsIndicators: false) {
HStack {
if let artist = self.model.artist {
ForEach(artist.similar.artist, id: \.name) {artist in
}.frame(width: g.size.width - 5, height: g.size.height * 0.7, alignment: .center)
Section {
Text("Top albums").font(.headline)
LazyVGrid(columns: [
GridItem(.flexible(minimum: 50, maximum: 200)),
GridItem(.flexible(minimum: 50, maximum: 200))
], spacing: 30 ) {
ForEach(model.albums, id: \.name) { album in
NavigationLink(
destination: Color(.red),
label: {
VStack {
KFImage.url(URL(string: artist.image[0].url )!)
KFImage.url(URL(string: album.image[0].url )!)
.resizable()
.loadImmediately()
.cornerRadius(5)
.aspectRatio(contentMode: .fill)
.frame(width: 150, height: 150)
.clipShape(Circle())
.cornerRadius(.infinity)

Text(artist.name).font(.subheadline)
Text(album.name).font(.headline).lineLimit(1).foregroundColor(.white)
Text("\(String(format: "%ld", locale: Locale.current, album.playcount) ) listeners")
.font(.subheadline)
.foregroundColor(.gray).lineLimit(1)
}
})

}
}
}.padding().offset(y: -50)

Section {
Text("Similar artists").font(.headline)
ScrollView(.horizontal, showsIndicators: false) {
HStack {
if let artist = self.model.artist {
ForEach(artist.similar.artist, id: \.name) {artist in
VStack {
KFImage.url(URL(string: artist.image[0].url )!)
.resizable()
.loadImmediately()
.aspectRatio(contentMode: .fill)
.frame(width: 150, height: 150)
.clipShape(Circle())
.cornerRadius(.infinity)

Text(artist.name).font(.subheadline)
.foregroundColor(.gray).lineLimit(1)
}
}
}
}
}
}.padding().offset(y: -30)
}.padding(.top, 10)
.onAppear {
self.model.getAll(artist)
}
}.padding().offset(y: -30)
}.padding(.top, 10)
.onAppear {
self.model.getArtistAlbums(self.artist.name)
self.model.getArtistTracks(self.artist.name)
self.model.getArtistInfo(self.artist.name)
}
}.navigationTitle(artist.name)
}.navigationTitle(artist.name)
}.opacity(model.isLoading ? 0 : 1)

// Show loader above the rest of the ZStack
if model.isLoading {
ProgressView()
Expand Down

0 comments on commit ed46f91

Please sign in to comment.