Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions App/Player/SongDetailsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ struct SongDetailsView: View {
.frame(width: 96, alignment: .leading)
Rating(stars: song.rating * 5) { stars in
session.rate(stars: stars)
model.toasts.show("Rated \(stars) stars")
if stars == stars.rounded() {
model.toasts.show("Rated \(Int(stars)) stars")
} else {
model.toasts.show("Rated \(stars.formatted()) stars")
}
}
}

Expand Down Expand Up @@ -141,25 +145,31 @@ private struct DetailRow: View {
}
}

/// Clementine's rating in half stars. Tapping a star rates the song that many stars.
/// Clementine's rating in half stars. Tapping a star rates the song that many stars, or half a
/// star less on its leading half. VoiceOver offers the half star as an action on each star.
private struct Rating: View {
let stars: Float
let rate: (Int) -> Void
let rate: (Float) -> Void

var body: some View {
HStack(spacing: 0) {
ForEach(1...5, id: \.self) { star in
Button {
rate(star)
} label: {
Image(systemName: symbol(star))
.font(.title3)
.foregroundStyle(Palette.primary)
.frame(width: 44, height: 44)
.contentShape(.rect)
}
.buttonStyle(.plain)
.accessibilityLabel("Rate \(star) stars")
let whole = Float(star)
let half = whole - 0.5
Image(systemName: symbol(star))
.font(.title3)
.foregroundStyle(Palette.primary)
.frame(width: 44, height: 44)
.contentShape(.rect)
// Local coordinates start from the leading edge, in right-to-left languages too.
.onTapGesture(coordinateSpace: .local) { location in
rate(location.x < 22 ? half : whole)
}
.accessibilityElement()
.accessibilityAddTraits(.isButton)
.accessibilityLabel("Rate \(star) stars")
.accessibilityAction { rate(whole) }
.accessibilityAction(named: "Rate \(half.formatted()) stars") { rate(half) }
}
}
.accessibilityElement(children: .contain)
Expand Down
6 changes: 6 additions & 0 deletions App/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -16894,6 +16894,9 @@
}
}
}
},
"Rate %@ stars" : {

},
"Rate %lld stars" : {
"localizations" : {
Expand Down Expand Up @@ -17072,6 +17075,9 @@
}
}
}
},
"Rated %@ stars" : {

},
"Rated %lld stars" : {
"localizations" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,10 @@ public final class RemoteSession {
return repeatMode
}

/// Rates the current song from 0 to 5 stars, showing it at once.
public func rate(stars: Int) {
/// Rates the current song from 0 to 5 stars, in half stars, showing it at once.
public func rate(stars: Float) {
guard song != nil else { return }
let rating = Float(max(0, min(5, stars))) / 5
let rating = (max(0, min(5, stars)) * 2).rounded() / 10
song?.rating = rating
send(Messages.rate(rating))
}
Expand Down
Loading