no chart padding, no charts when no last.fm, rename, closes #20
This commit is contained in:
parent
702d9b1733
commit
a8842eefc7
@ -27,7 +27,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
let liveUser = LiveUser(playlists: [], tags: [], username: keychain["username"] ?? "", loggedIn: false).loadUserDefaults()
|
||||
let liveUser = LiveUser(playlists: [], tags: [], username: keychain["username"] ?? "", loggedIn: false).load_user_defaults()
|
||||
|
||||
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(liveUser))
|
||||
self.window = window
|
||||
|
@ -43,6 +43,16 @@ class LiveUser: ObservableObject {
|
||||
self.user = user
|
||||
}
|
||||
|
||||
func lastfm_connected() -> Bool {
|
||||
if let username = user?.lastfm_username {
|
||||
if username.count > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func logout() {
|
||||
let keychain = Keychain(service: "xyz.sarsoo.music.login")
|
||||
|
||||
@ -65,20 +75,20 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func updatePlaylist(playlistIn: Playlist) {
|
||||
func update_playlist(playlistIn: Playlist) {
|
||||
guard let index = self.playlists.firstIndex(of: playlistIn) else {
|
||||
fatalError("\(playlistIn) not found")
|
||||
}
|
||||
self.playlists[index] = playlistIn
|
||||
}
|
||||
|
||||
func refreshUser(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
|
||||
func refresh_user(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
|
||||
self.isRefreshingUser = true
|
||||
|
||||
let api = UserApi.getUser
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.checkNetworkResponse(response: response) {
|
||||
if self.check_network_response(response: response) {
|
||||
|
||||
guard let data = response.data else {
|
||||
fatalError("error getting user")
|
||||
@ -106,13 +116,13 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func refreshPlaylists(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
|
||||
func refresh_playlists(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
|
||||
self.isRefreshingPlaylists = true
|
||||
|
||||
let api = PlaylistApi.getPlaylists
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.checkNetworkResponse(response: response) {
|
||||
if self.check_network_response(response: response) {
|
||||
|
||||
guard let data = response.data else {
|
||||
fatalError("error getting playlists")
|
||||
@ -149,13 +159,13 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTags(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
|
||||
func refresh_tags(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
|
||||
self.isRefreshingTags = true
|
||||
|
||||
let api = TagApi.getTags
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.checkNetworkResponse(response: response) {
|
||||
if self.check_network_response(response: response) {
|
||||
|
||||
guard let data = response.data else {
|
||||
fatalError("error getting tags")
|
||||
@ -192,7 +202,7 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func checkNetworkResponse(response: AFDataResponse<Any>) -> Bool {
|
||||
func check_network_response(response: AFDataResponse<Any>) -> Bool {
|
||||
|
||||
if let statusCode = response.response?.statusCode {
|
||||
switch statusCode {
|
||||
@ -211,7 +221,7 @@ class LiveUser: ObservableObject {
|
||||
return false
|
||||
}
|
||||
|
||||
func loadUserDefaults() -> LiveUser {
|
||||
func load_user_defaults() -> LiveUser {
|
||||
let defaults = UserDefaults.standard
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
|
@ -26,7 +26,7 @@ class User: Identifiable, Decodable {
|
||||
var last_keygen: String
|
||||
|
||||
var spotify_linked: Bool
|
||||
var lastfm_username: String?
|
||||
@Published var lastfm_username: String?
|
||||
|
||||
//MARK: Initialization
|
||||
|
||||
@ -48,5 +48,51 @@ class User: Identifiable, Decodable {
|
||||
self.spotify_linked = spotify_linked
|
||||
self.lastfm_username = lastfm_username
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case username
|
||||
case email
|
||||
case type
|
||||
|
||||
case last_login
|
||||
case last_keygen
|
||||
|
||||
case spotify_linked
|
||||
case lastfm_username
|
||||
}
|
||||
|
||||
required init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
username = try container.decode(String.self, forKey: .username)
|
||||
do{
|
||||
email = try container.decode(String.self, forKey: .email)
|
||||
}catch {
|
||||
email = nil
|
||||
debugPrint("failed to parse email")
|
||||
}
|
||||
|
||||
type = try container.decode(UserType.self, forKey: .type)
|
||||
|
||||
last_login = try container.decode(String.self, forKey: .last_login)
|
||||
last_keygen = try container.decode(String.self, forKey: .last_keygen)
|
||||
|
||||
spotify_linked = try container.decode(Bool.self, forKey: .spotify_linked)
|
||||
lastfm_username = try container.decode(String.self, forKey: .lastfm_username)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(self.username, forKey: .username)
|
||||
try container.encode(self.email, forKey: .email)
|
||||
try container.encode(self.type.rawValue, forKey: .type)
|
||||
|
||||
try container.encode(self.last_login, forKey: .last_login)
|
||||
try container.encode(self.last_keygen, forKey: .last_keygen)
|
||||
|
||||
try container.encode(self.spotify_linked, forKey: .spotify_linked)
|
||||
try container.encode(self.lastfm_username, forKey: .lastfm_username)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,9 +69,9 @@ struct AppSkeleton: View {
|
||||
}
|
||||
|
||||
private func fetchAll() {
|
||||
self.liveUser.refreshUser()
|
||||
self.liveUser.refreshPlaylists()
|
||||
self.liveUser.refreshTags()
|
||||
self.liveUser.refresh_user()
|
||||
self.liveUser.refresh_playlists()
|
||||
self.liveUser.refresh_tags()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ struct AddPlaylistSheet: View {
|
||||
type: PlaylistType(rawValue: selectedType) ?? .defaultPlaylist)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
self.playlists.append(playlist)
|
||||
self.playlists = self.playlists.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
|
||||
|
@ -13,14 +13,21 @@ struct Name: Identifiable, Hashable {
|
||||
var name: String
|
||||
}
|
||||
|
||||
enum PlaylistInputType {
|
||||
case MixonomerPlaylists
|
||||
case SpotifyPlaylists
|
||||
}
|
||||
|
||||
struct PlaylistInputList: View {
|
||||
|
||||
@Binding var names: [String]
|
||||
var nameType: String
|
||||
var type: PlaylistInputType
|
||||
|
||||
init(names: Binding<[String]>, nameType: String){
|
||||
init(names: Binding<[String]>, nameType: String, type: PlaylistInputType){
|
||||
self.nameType = nameType
|
||||
self._names = names
|
||||
self.type = type
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@ -41,12 +48,14 @@ struct PlaylistInputList: View {
|
||||
}
|
||||
// .id(UUID())
|
||||
.navigationBarTitle(nameType)
|
||||
.navigationBarItems(trailing:
|
||||
Button(
|
||||
action: { },
|
||||
label: { Image(systemName: "plus.circle") }
|
||||
)
|
||||
)
|
||||
// .navigationBarItems(trailing:
|
||||
// Button(
|
||||
// action: {
|
||||
//
|
||||
// },
|
||||
// label: { Image(systemName: "plus.circle") }
|
||||
// )
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +63,6 @@ struct PlaylistInputList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
PlaylistInputList(names: .constant([
|
||||
"name"
|
||||
]), nameType: "Spotify Playlists")
|
||||
]), nameType: "Spotify Playlists", type: .MixonomerPlaylists)
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ struct PlaylistList: View {
|
||||
let api = PlaylistApi.deletePlaylist(name: self.liveUser.playlists[index].name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
} else {
|
||||
|
||||
@ -58,7 +58,7 @@ struct PlaylistList: View {
|
||||
}
|
||||
.refreshable
|
||||
{
|
||||
self.liveUser.refreshPlaylists(onSuccess: {
|
||||
self.liveUser.refresh_playlists(onSuccess: {
|
||||
|
||||
toastText = "Refreshed!"
|
||||
toastSuccess = true
|
||||
|
@ -31,7 +31,7 @@ struct PlaylistRow: View {
|
||||
.validate()
|
||||
.responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
}
|
||||
else {
|
||||
|
@ -24,9 +24,23 @@ struct PlaylistView: View {
|
||||
@State private var toastText = ""
|
||||
@State private var toastSuccess = true
|
||||
|
||||
var chartStyle: ChartStyle {
|
||||
var trackChartStyle: ChartStyle {
|
||||
get {
|
||||
let _style = ChartStyle(backgroundColor: .white, accentColor: .red, gradientColor: GradientColors.bluPurpl, textColor: .black, legendTextColor: .gray)
|
||||
let _style = ChartStyle(backgroundColor: .white, accentColor: Color(red: 0.4765, green: 0.5976, blue: 0.7578), gradientColor: GradientColors.bluPurpl, textColor: .black, legendTextColor: .gray)
|
||||
return _style
|
||||
}
|
||||
}
|
||||
|
||||
var albumChartStyle: ChartStyle {
|
||||
get {
|
||||
let _style = ChartStyle(backgroundColor: .white, accentColor: Color(red: 0.6367, green: 0.2968, blue: 0.4648), gradientColor: GradientColors.bluPurpl, textColor: .black, legendTextColor: .gray)
|
||||
return _style
|
||||
}
|
||||
}
|
||||
|
||||
var artistChartStyle: ChartStyle {
|
||||
get {
|
||||
let _style = ChartStyle(backgroundColor: .white, accentColor: Color(red: 0.3476, green: 0.5195, blue: 0.3359), gradientColor: GradientColors.bluPurpl, textColor: .black, legendTextColor: .gray)
|
||||
return _style
|
||||
}
|
||||
}
|
||||
@ -35,6 +49,9 @@ struct PlaylistView: View {
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
|
||||
if liveUser.lastfm_connected() {
|
||||
|
||||
Section(header: Text("Stats")){
|
||||
HStack {
|
||||
Text("Track Count")
|
||||
@ -80,27 +97,29 @@ struct PlaylistView: View {
|
||||
data: [Double(self.playlist.lastfm_stat_percent), Double(100 - self.playlist.lastfm_stat_percent)],
|
||||
title: "Tracks",
|
||||
legend:"Listening",
|
||||
style: chartStyle,
|
||||
style: trackChartStyle,
|
||||
form: chartSize)
|
||||
Spacer(minLength: 20)
|
||||
PieChartView(
|
||||
data: [Double(self.playlist.lastfm_stat_album_percent), Double(100 - self.playlist.lastfm_stat_album_percent)],
|
||||
title: "Albums",
|
||||
legend:"Listening",
|
||||
style: chartStyle,
|
||||
style: albumChartStyle,
|
||||
form: chartSize)
|
||||
Spacer(minLength: 20)
|
||||
PieChartView(
|
||||
data: [Double(self.playlist.lastfm_stat_artist_percent), Double(100 - self.playlist.lastfm_stat_artist_percent)],
|
||||
title: "Artists",
|
||||
legend:"Listening",
|
||||
style: chartStyle,
|
||||
style: artistChartStyle,
|
||||
form: chartSize)
|
||||
Spacer()
|
||||
}
|
||||
.padding([.vertical], 20)
|
||||
.padding([.horizontal], 10)
|
||||
}
|
||||
.listRowInsets(EdgeInsets())
|
||||
}
|
||||
|
||||
Section(header: Text("Options")){
|
||||
Toggle(isOn: self.$playlist.include_recommendations) {
|
||||
@ -168,7 +187,7 @@ struct PlaylistView: View {
|
||||
}
|
||||
}
|
||||
Section(header: Text("Inputs")){
|
||||
NavigationLink(destination: PlaylistInputList(names: self.$playlist.playlist_references, nameType: "Managed Playlists")) {
|
||||
NavigationLink(destination: PlaylistInputList(names: self.$playlist.playlist_references, nameType: "Managed Playlists", type: .MixonomerPlaylists)) {
|
||||
HStack {
|
||||
Text("Managed Playlists")
|
||||
Spacer()
|
||||
@ -177,7 +196,7 @@ struct PlaylistView: View {
|
||||
}
|
||||
}
|
||||
|
||||
NavigationLink(destination: PlaylistInputList(names: self.$playlist.parts, nameType: "Spotify Playlists")) {
|
||||
NavigationLink(destination: PlaylistInputList(names: self.$playlist.parts, nameType: "Spotify Playlists", type: .SpotifyPlaylists)) {
|
||||
HStack {
|
||||
Text("Spotify Playlists")
|
||||
Spacer()
|
||||
@ -225,7 +244,7 @@ struct PlaylistView: View {
|
||||
.validate()
|
||||
.responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
toastText = "Running!"
|
||||
toastSuccess = true
|
||||
@ -244,7 +263,7 @@ struct PlaylistView: View {
|
||||
let api = PlaylistApi.refreshStats(name: playlist.name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
toastText = "Refreshing Stats!"
|
||||
toastSuccess = true
|
||||
@ -270,7 +289,7 @@ struct PlaylistView: View {
|
||||
let api = PlaylistApi.updatePlaylist(name: playlist.name, updates: updates)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
debugPrint("success")
|
||||
} else {
|
||||
debugPrint("error")
|
||||
@ -283,7 +302,7 @@ struct PlaylistView: View {
|
||||
let api = PlaylistApi.getPlaylist(name: self.playlist.name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
guard let data = response.data else {
|
||||
fatalError("error getting playlist")
|
||||
|
@ -53,7 +53,7 @@ struct SettingsList: View {
|
||||
let api = UserApi.deleteUser
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
self.liveUser.logout()
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ struct AddTagSheet: View {
|
||||
let api = TagApi.newTag(tag_id: tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
self.tags.append(tag)
|
||||
self.tags = self.tags.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
|
||||
|
@ -31,7 +31,7 @@ struct TagList: View {
|
||||
let api = TagApi.deleteTag(tag_id: self.liveUser.tags[index].tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
}
|
||||
else {
|
||||
@ -47,7 +47,7 @@ struct TagList: View {
|
||||
}
|
||||
}
|
||||
.refreshable {
|
||||
self.liveUser.refreshTags(onSuccess: {
|
||||
self.liveUser.refresh_tags(onSuccess: {
|
||||
|
||||
toastText = "Refreshed!"
|
||||
toastSuccess = true
|
||||
|
@ -64,12 +64,12 @@ struct TagObjList: View {
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(Text(objType))
|
||||
.navigationBarItems(trailing:
|
||||
Button(
|
||||
action: { },
|
||||
label: { Image(systemName: "plus.circle") }
|
||||
)
|
||||
)
|
||||
// .navigationBarItems(trailing:
|
||||
// Button(
|
||||
// action: { },
|
||||
// label: { Image(systemName: "plus.circle") }
|
||||
// )
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ struct TagRow: View {
|
||||
.validate()
|
||||
.responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
} else {
|
||||
self.showingNetworkError = true
|
||||
|
@ -120,7 +120,7 @@ struct TagView: View {
|
||||
let api = TagApi.runTag(tag_id: tag.tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
} else {
|
||||
|
||||
@ -133,7 +133,7 @@ struct TagView: View {
|
||||
let api = TagApi.updateTag(tag_id: tag.tag_id, updates: updates)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
} else {
|
||||
|
||||
@ -146,7 +146,7 @@ struct TagView: View {
|
||||
let api = TagApi.getTag(tag_id: self.tag.tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.checkNetworkResponse(response: response) {
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
guard let data = response.data else {
|
||||
fatalError("error getting tag")
|
||||
|
Loading…
Reference in New Issue
Block a user