add refresh stats button, added playlist stat graphs, updated settings list
This commit is contained in:
parent
7c763e360a
commit
4e8668a4b2
@ -25,6 +25,7 @@ public enum PlaylistApi {
|
|||||||
case deletePlaylist(name: String)
|
case deletePlaylist(name: String)
|
||||||
case newPlaylist(name: String, type: PlaylistType)
|
case newPlaylist(name: String, type: PlaylistType)
|
||||||
case getPlaylist(name: String)
|
case getPlaylist(name: String)
|
||||||
|
case refreshStats(name: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PlaylistApi: ApiRequest {
|
extension PlaylistApi: ApiRequest {
|
||||||
@ -46,6 +47,8 @@ extension PlaylistApi: ApiRequest {
|
|||||||
return "api/playlist"
|
return "api/playlist"
|
||||||
case .getPlaylist:
|
case .getPlaylist:
|
||||||
return "api/playlist"
|
return "api/playlist"
|
||||||
|
case .refreshStats:
|
||||||
|
return "api/spotfm/playlist/refresh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +66,8 @@ extension PlaylistApi: ApiRequest {
|
|||||||
return .put
|
return .put
|
||||||
case .getPlaylist:
|
case .getPlaylist:
|
||||||
return .get
|
return .get
|
||||||
|
case .refreshStats:
|
||||||
|
return .get
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +87,8 @@ extension PlaylistApi: ApiRequest {
|
|||||||
return JSON(["name": name, "type": txTypeHeaders[type.rawValue]])
|
return JSON(["name": name, "type": txTypeHeaders[type.rawValue]])
|
||||||
case .getPlaylist(let name):
|
case .getPlaylist(let name):
|
||||||
return JSON(["name": name])
|
return JSON(["name": name])
|
||||||
|
case .refreshStats(let name):
|
||||||
|
return JSON(["name": name])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +106,8 @@ extension PlaylistApi: ApiRequest {
|
|||||||
return JSONParameterEncoder.default
|
return JSONParameterEncoder.default
|
||||||
case .getPlaylist:
|
case .getPlaylist:
|
||||||
return URLEncodedFormParameterEncoder()
|
return URLEncodedFormParameterEncoder()
|
||||||
|
case .refreshStats:
|
||||||
|
return URLEncodedFormParameterEncoder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftUIRefresh
|
import SwiftUIRefresh
|
||||||
import SwiftyJSON
|
import SwiftyJSON
|
||||||
|
import SwiftUICharts
|
||||||
|
|
||||||
struct PlaylistView: View {
|
struct PlaylistView: View {
|
||||||
|
|
||||||
@ -25,6 +26,13 @@ struct PlaylistView: View {
|
|||||||
|
|
||||||
@State private var isRefreshing = false
|
@State private var isRefreshing = false
|
||||||
|
|
||||||
|
var chartStyle: ChartStyle {
|
||||||
|
get {
|
||||||
|
let _style = ChartStyle(backgroundColor: .white, accentColor: .red, gradientColor: GradientColors.bluPurpl, textColor: .black, legendTextColor: .gray)
|
||||||
|
return _style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
Section(header: Text("Stats")){
|
Section(header: Text("Stats")){
|
||||||
@ -58,7 +66,38 @@ struct PlaylistView: View {
|
|||||||
.font(.body)
|
.font(.body)
|
||||||
.foregroundColor(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
}
|
}
|
||||||
|
Button(action: {
|
||||||
|
self.refreshStats()
|
||||||
|
}){
|
||||||
|
Text("Refresh")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
PieChartView(
|
||||||
|
data: [Double(self.playlist.lastfm_stat_percent), Double(100 - self.playlist.lastfm_stat_percent)],
|
||||||
|
title: "Tracks",
|
||||||
|
legend:"Listening",
|
||||||
|
style: chartStyle,
|
||||||
|
form: ChartForm.medium)
|
||||||
|
PieChartView(
|
||||||
|
data: [Double(self.playlist.lastfm_stat_album_percent), Double(100 - self.playlist.lastfm_stat_album_percent)],
|
||||||
|
title: "Albums",
|
||||||
|
legend:"Listening",
|
||||||
|
style: chartStyle,
|
||||||
|
form: ChartForm.medium)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
PieChartView(
|
||||||
|
data: [Double(self.playlist.lastfm_stat_artist_percent), Double(100 - self.playlist.lastfm_stat_artist_percent)],
|
||||||
|
title: "Artists",
|
||||||
|
legend:"Listening",
|
||||||
|
style: chartStyle,
|
||||||
|
form: ChartForm.medium)
|
||||||
|
}
|
||||||
|
|
||||||
Section(header: Text("Options")){
|
Section(header: Text("Options")){
|
||||||
Toggle(isOn: self.$playlist.include_recommendations) {
|
Toggle(isOn: self.$playlist.include_recommendations) {
|
||||||
Text("Spotify Recommendations")
|
Text("Spotify Recommendations")
|
||||||
@ -190,6 +229,14 @@ struct PlaylistView: View {
|
|||||||
//TODO: do better error checking
|
//TODO: do better error checking
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func refreshStats() {
|
||||||
|
let api = PlaylistApi.refreshStats(name: playlist.name)
|
||||||
|
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||||
|
|
||||||
|
}
|
||||||
|
//TODO: do better error checking
|
||||||
|
}
|
||||||
|
|
||||||
func openPlaylist() {
|
func openPlaylist() {
|
||||||
if let url = URL(string: self.playlist.link) {
|
if let url = URL(string: self.playlist.link) {
|
||||||
UIApplication.shared.open(url)
|
UIApplication.shared.open(url)
|
||||||
|
@ -18,29 +18,55 @@ struct SettingsList: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
VStack{
|
VStack{
|
||||||
List{
|
List{
|
||||||
Button(action: {
|
Section {
|
||||||
if let url = URL(string: "https://music.sarsoo.xyz") {
|
Button(action: {
|
||||||
UIApplication.shared.open(url)
|
if let url = URL(string: "https://music.sarsoo.xyz") {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Launch Web Version")
|
||||||
}
|
}
|
||||||
}) {
|
Button(action: {
|
||||||
Text("Open Web")
|
let keychain = Keychain(service: "xyz.sarsoo.music.login")
|
||||||
}
|
do {
|
||||||
Button(action: {
|
try keychain.remove("username")
|
||||||
let keychain = Keychain(service: "xyz.sarsoo.music.login")
|
try keychain.remove("password")
|
||||||
do {
|
} catch let error {
|
||||||
try keychain.remove("username")
|
debugPrint("Could not clear keychain, \(error)")
|
||||||
try keychain.remove("password")
|
}
|
||||||
} catch let error {
|
}) {
|
||||||
debugPrint("Could not clear keychain, \(error)")
|
Text("Log out")
|
||||||
}
|
}
|
||||||
}) {
|
|
||||||
Text("Log out")
|
|
||||||
}
|
}
|
||||||
}
|
Section(
|
||||||
Image("APFooter")
|
header:
|
||||||
.resizable()
|
Text("Development"),
|
||||||
.aspectRatio(contentMode: .fit)
|
footer:
|
||||||
.frame(width: 100.0)
|
HStack{
|
||||||
|
Spacer()
|
||||||
|
Image("APFooter")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 100.0)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Button(action: {
|
||||||
|
if let url = URL(string: "https://github.com/sarsoo/music-tools") {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Server Source")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
if let url = URL(string: "https://github.com/sarsoo/music-tools-ios") {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("iOS Source")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.listStyle(GroupedListStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,11 +89,13 @@ struct TagView: View {
|
|||||||
.filter {
|
.filter {
|
||||||
$0["count"].intValue > 0
|
$0["count"].intValue > 0
|
||||||
}
|
}
|
||||||
.map {
|
.sorted {
|
||||||
|
$0["name"].stringValue.lowercased() < $1["name"].stringValue.lowercased()
|
||||||
|
}.map {
|
||||||
($0["name"].stringValue, $0["count"].intValue)
|
($0["name"].stringValue, $0["count"].intValue)
|
||||||
}),
|
}),
|
||||||
title: "Scrobbles",
|
title: self.tag.name,
|
||||||
style: chartStyle,
|
legend: "Scrobbles", style: chartStyle,
|
||||||
form: ChartForm.medium,
|
form: ChartForm.medium,
|
||||||
cornerImage: Image(systemName: "music.note")
|
cornerImage: Image(systemName: "music.note")
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user