restructured main views, added totals to rows
This commit is contained in:
parent
6d3929a173
commit
fced8c9fc3
@ -26,6 +26,8 @@
|
||||
E98254D023FB00B60056D9D3 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98254CF23FB00B60056D9D3 /* LoginScreen.swift */; };
|
||||
E98254D923FB53780056D9D3 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = E98254D823FB53780056D9D3 /* Alamofire */; };
|
||||
E98254DB23FB64740056D9D3 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98254DA23FB64740056D9D3 /* Network.swift */; };
|
||||
E9CCD5BB2454C57300B5CD6C /* PlaylistList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CCD5BA2454C57300B5CD6C /* PlaylistList.swift */; };
|
||||
E9CCD5BD2454C64300B5CD6C /* TagList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CCD5BC2454C64300B5CD6C /* TagList.swift */; };
|
||||
E9E30C2623FEA4F000574EEF /* TagApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2523FEA4EF00574EEF /* TagApi.swift */; };
|
||||
E9E30C2823FEA6BD00574EEF /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2723FEA6BD00574EEF /* Tag.swift */; };
|
||||
E9E30C2A23FEAA3A00574EEF /* TagRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2923FEAA3A00574EEF /* TagRow.swift */; };
|
||||
@ -74,6 +76,8 @@
|
||||
E98254C923FA26600056D9D3 /* PlaylistRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistRow.swift; sourceTree = "<group>"; };
|
||||
E98254CF23FB00B60056D9D3 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = "<group>"; };
|
||||
E98254DA23FB64740056D9D3 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = "<group>"; };
|
||||
E9CCD5BA2454C57300B5CD6C /* PlaylistList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistList.swift; sourceTree = "<group>"; };
|
||||
E9CCD5BC2454C64300B5CD6C /* TagList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagList.swift; sourceTree = "<group>"; };
|
||||
E9E30C2523FEA4EF00574EEF /* TagApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagApi.swift; sourceTree = "<group>"; };
|
||||
E9E30C2723FEA6BD00574EEF /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = "<group>"; };
|
||||
E9E30C2923FEAA3A00574EEF /* TagRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagRow.swift; sourceTree = "<group>"; };
|
||||
@ -178,6 +182,7 @@
|
||||
E98254C923FA26600056D9D3 /* PlaylistRow.swift */,
|
||||
E97AF46623FD650800635494 /* AddPlaylistSheet.swift */,
|
||||
E97AF46823FD9E1B00635494 /* PlaylistInputList.swift */,
|
||||
E9CCD5BA2454C57300B5CD6C /* PlaylistList.swift */,
|
||||
);
|
||||
path = Playlist;
|
||||
sourceTree = "<group>";
|
||||
@ -189,6 +194,7 @@
|
||||
E9E30C2C23FEAB0200574EEF /* TagView.swift */,
|
||||
E9E30C3023FEAF2B00574EEF /* TagObjList.swift */,
|
||||
E934AC98240DD0E4009869F4 /* AddTagSheet.swift */,
|
||||
E9CCD5BC2454C64300B5CD6C /* TagList.swift */,
|
||||
);
|
||||
path = Tag;
|
||||
sourceTree = "<group>";
|
||||
@ -417,7 +423,9 @@
|
||||
E9E30C3323FF255C00574EEF /* SettingsList.swift in Sources */,
|
||||
E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */,
|
||||
E98254DB23FB64740056D9D3 /* Network.swift in Sources */,
|
||||
E9CCD5BD2454C64300B5CD6C /* TagList.swift in Sources */,
|
||||
E9E30C2A23FEAA3A00574EEF /* TagRow.swift in Sources */,
|
||||
E9CCD5BB2454C57300B5CD6C /* PlaylistList.swift in Sources */,
|
||||
E97AF46023FC85D600635494 /* PlaylistApi.swift in Sources */,
|
||||
E9EA690F23F9A5430012C3E8 /* AppSkeleton.swift in Sources */,
|
||||
E98254BD23F9B7A90056D9D3 /* Playlist.swift in Sources */,
|
||||
|
@ -15,15 +15,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
|
||||
let keychain = Keychain(service: "xyz.sarsoo.music.login")
|
||||
// do {
|
||||
// try keychain.remove("username")
|
||||
// try keychain.remove("password")
|
||||
// } catch let error {
|
||||
// debugPrint("Could not clear keychain, \(error)")
|
||||
// }
|
||||
//
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -27,13 +27,9 @@ 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()
|
||||
|
||||
|
||||
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(liveUser))
|
||||
// window.rootViewController = UIHostingController(rootView: contentView.environmentObject(liveUser))
|
||||
// window.rootViewController = LoginController()
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
@ -66,7 +62,5 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// Root level view loaded by delegate to show either main app or login screen
|
||||
struct Router: View {
|
||||
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
|
@ -16,52 +16,11 @@ struct AppSkeleton: View {
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
|
||||
@State private var selection = 0 // Tab view selection
|
||||
@State private var showAdd = false // State for showing add modal view
|
||||
|
||||
var body: some View {
|
||||
TabView {
|
||||
|
||||
// PLAYLISTS
|
||||
NavigationView {
|
||||
List{
|
||||
if(liveUser.playlists.count > 0){
|
||||
ForEach(liveUser.playlists.indices, id:\.self) { idx in
|
||||
PlaylistRow(playlist: self.$liveUser.playlists[idx])
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
|
||||
indexSet.forEach { index in
|
||||
let api = PlaylistApi.deletePlaylist(name: self.liveUser.playlists[index].name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
self.liveUser.playlists.remove(atOffsets: indexSet)
|
||||
}
|
||||
}else {
|
||||
HStack {
|
||||
Text("No Playlists")
|
||||
.multilineTextAlignment(.center)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.pullToRefresh(isShowing: self.$liveUser.isRefreshingPlaylists) {
|
||||
self.liveUser.refreshPlaylists()
|
||||
}
|
||||
.navigationBarTitle(Text("Playlists").font(.title))
|
||||
|
||||
// add playlist button
|
||||
.navigationBarItems(trailing:
|
||||
Button(
|
||||
action: { self.showAdd = true },
|
||||
label: { Text("Add") }
|
||||
).sheet(isPresented: $showAdd) {
|
||||
AddPlaylistSheet(playlists: self.$liveUser.playlists, username: self.$liveUser.username)
|
||||
}
|
||||
)
|
||||
}
|
||||
PlaylistList()
|
||||
.tabItem {
|
||||
VStack {
|
||||
Image(systemName: "music.note.list")
|
||||
@ -70,47 +29,7 @@ struct AppSkeleton: View {
|
||||
}
|
||||
.tag(0)
|
||||
|
||||
// TAGS
|
||||
NavigationView {
|
||||
List{
|
||||
if(liveUser.tags.count > 0) {
|
||||
ForEach(liveUser.tags.indices, id:\.self) { idx in
|
||||
TagRow(tag: self.$liveUser.tags[idx])
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
|
||||
indexSet.forEach { index in
|
||||
let api = TagApi.deleteTag(tag_id: self.liveUser.tags[index].tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
self.liveUser.tags.remove(atOffsets: indexSet)
|
||||
}
|
||||
} else {
|
||||
HStack {
|
||||
Text("No Tags")
|
||||
.multilineTextAlignment(.center)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.pullToRefresh(isShowing: self.$liveUser.isRefreshingTags) {
|
||||
self.liveUser.refreshTags()
|
||||
}
|
||||
.navigationBarTitle(Text("Tags").font(.title))
|
||||
|
||||
// add playlist button
|
||||
.navigationBarItems(trailing:
|
||||
Button(
|
||||
action: { self.showAdd = true },
|
||||
label: { Text("Add") }
|
||||
).sheet(isPresented: $showAdd) {
|
||||
AddTagSheet(tags: self.$liveUser.tags, username: self.$liveUser.username)
|
||||
}
|
||||
)
|
||||
}
|
||||
TagList()
|
||||
.tabItem {
|
||||
VStack {
|
||||
Image(systemName: "tag")
|
||||
@ -119,17 +38,15 @@ struct AppSkeleton: View {
|
||||
}
|
||||
.tag(1)
|
||||
|
||||
// SETTINGS
|
||||
NavigationView {
|
||||
SettingsList()
|
||||
.navigationBarTitle(Text("Settings").font(.title))
|
||||
}.tabItem {
|
||||
.tabItem {
|
||||
VStack {
|
||||
Image(systemName: "slider.horizontal.3")
|
||||
Text("Settings")
|
||||
}
|
||||
}
|
||||
.tag(2)
|
||||
|
||||
}.onAppear {
|
||||
self.fetchAll()
|
||||
}
|
||||
|
58
Music Tools/Views/Playlist/PlaylistList.swift
Normal file
58
Music Tools/Views/Playlist/PlaylistList.swift
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// PlaylistList.swift
|
||||
// Music Tools
|
||||
//
|
||||
// Created by Andy Pack on 25/04/2020.
|
||||
// Copyright © 2020 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PlaylistList: View {
|
||||
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
@State private var showAdd = false // State for showing add modal view
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List{
|
||||
if(liveUser.playlists.count > 0){
|
||||
ForEach(liveUser.playlists.indices, id:\.self) { idx in
|
||||
PlaylistRow(playlist: self.$liveUser.playlists[idx])
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
|
||||
indexSet.forEach { index in
|
||||
let api = PlaylistApi.deletePlaylist(name: self.liveUser.playlists[index].name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
self.liveUser.playlists.remove(atOffsets: indexSet)
|
||||
}
|
||||
}else {
|
||||
Text("No Playlists")
|
||||
}
|
||||
}
|
||||
.pullToRefresh(isShowing: self.$liveUser.isRefreshingPlaylists) {
|
||||
self.liveUser.refreshPlaylists()
|
||||
}
|
||||
.navigationBarTitle(Text("Playlists 📻"))
|
||||
.navigationBarItems(trailing:
|
||||
Button(
|
||||
action: { self.showAdd = true },
|
||||
label: { Text("Add") }
|
||||
).sheet(isPresented: $showAdd) {
|
||||
AddPlaylistSheet(playlists: self.$liveUser.playlists, username: self.$liveUser.username)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PlaylistList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
PlaylistList()
|
||||
}
|
||||
}
|
@ -10,26 +10,36 @@ import SwiftUI
|
||||
import SwiftyJSON
|
||||
|
||||
struct PlaylistRow: View {
|
||||
|
||||
@Binding var playlist: Playlist
|
||||
@State private var showingNetworkError = false
|
||||
|
||||
var body: some View {
|
||||
NavigationLink(destination: PlaylistView(playlist: $playlist)){
|
||||
HStack {
|
||||
Text(playlist.name)
|
||||
.contextMenu {
|
||||
|
||||
// run force touch
|
||||
if playlist.lastfm_stat_count > 0 {
|
||||
Spacer()
|
||||
Text("\(playlist.lastfm_stat_count)")
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}.contextMenu {
|
||||
Button(action: {
|
||||
let api = PlaylistApi.runPlaylist(name: self.playlist.name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
RequestBuilder.buildRequest(apiRequest: api)
|
||||
.validate()
|
||||
.responseJSON{ response in
|
||||
switch response.result {
|
||||
case .success:
|
||||
break
|
||||
case .failure:
|
||||
self.showingNetworkError = true
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text("Refresh")
|
||||
Image(systemName: "arrow.clockwise.circle")
|
||||
}
|
||||
|
||||
// open force touch
|
||||
Button(action: {
|
||||
if let url = URL(string: self.playlist.link) {
|
||||
UIApplication.shared.open(url)
|
||||
@ -38,7 +48,9 @@ struct PlaylistRow: View {
|
||||
Text("Open")
|
||||
Image(systemName: "arrowshape.turn.up.right.circle")
|
||||
}
|
||||
}
|
||||
}.alert(isPresented: $showingNetworkError) {
|
||||
Alert(title: Text("Network Error"),
|
||||
message: Text("Could not refresh playlist"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ struct PlaylistView: View {
|
||||
|
||||
@State private var showingSheet = false
|
||||
@State private var isRefreshing = false
|
||||
@State private var showingNetworkError = false
|
||||
|
||||
var chartStyle: ChartStyle {
|
||||
get {
|
||||
@ -211,6 +212,10 @@ struct PlaylistView: View {
|
||||
self.$chart_limit.wrappedValue = playlist.chart_limit
|
||||
}
|
||||
}
|
||||
.alert(isPresented: $showingNetworkError) {
|
||||
Alert(title: Text("Network Error"),
|
||||
message: Text("Could not refresh playlist"))
|
||||
}
|
||||
}
|
||||
|
||||
func changeChartRange(newRange: LastFmRange) {
|
||||
@ -222,8 +227,15 @@ struct PlaylistView: View {
|
||||
|
||||
func runPlaylist() {
|
||||
let api = PlaylistApi.runPlaylist(name: playlist.name)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
RequestBuilder.buildRequest(apiRequest: api)
|
||||
.validate()
|
||||
.responseJSON{ response in
|
||||
switch response.result {
|
||||
case .success:
|
||||
break
|
||||
case .failure:
|
||||
self.showingNetworkError = true
|
||||
}
|
||||
}
|
||||
//TODO: do better error checking
|
||||
}
|
||||
|
@ -13,12 +13,8 @@ struct SettingsList: View {
|
||||
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
|
||||
init(){
|
||||
UITableView.appearance().tableFooterView = UIView()
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack{
|
||||
NavigationView {
|
||||
List{
|
||||
Section {
|
||||
Button(action: {
|
||||
@ -71,7 +67,9 @@ struct SettingsList: View {
|
||||
Text("iOS Source")
|
||||
}
|
||||
}
|
||||
}.listStyle(GroupedListStyle())
|
||||
}
|
||||
.listStyle(GroupedListStyle())
|
||||
.navigationBarTitle(Text("Settings ⚡️").font(.title))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
Music Tools/Views/Tag/TagList.swift
Normal file
62
Music Tools/Views/Tag/TagList.swift
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// TagList.swift
|
||||
// Music Tools
|
||||
//
|
||||
// Created by Andy Pack on 25/04/2020.
|
||||
// Copyright © 2020 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TagList: View {
|
||||
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
@State private var showAdd = false // State for showing add modal view
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List{
|
||||
if(liveUser.tags.count > 0) {
|
||||
ForEach(liveUser.tags.indices, id:\.self) { idx in
|
||||
TagRow(tag: self.$liveUser.tags[idx])
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
|
||||
indexSet.forEach { index in
|
||||
let api = TagApi.deleteTag(tag_id: self.liveUser.tags[index].tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
self.liveUser.tags.remove(atOffsets: indexSet)
|
||||
}
|
||||
} else {
|
||||
Text("No Tags")
|
||||
}
|
||||
}
|
||||
.pullToRefresh(isShowing: self.$liveUser.isRefreshingTags) {
|
||||
self.liveUser.refreshTags()
|
||||
}
|
||||
.navigationBarTitle(Text("Tags 🎷"))
|
||||
.navigationBarItems(
|
||||
leading:
|
||||
EditButton(),
|
||||
|
||||
trailing:
|
||||
Button(
|
||||
action: { self.showAdd = true },
|
||||
label: { Text("Add") }
|
||||
).sheet(isPresented: $showAdd) {
|
||||
AddTagSheet(tags: self.$liveUser.tags, username: self.$liveUser.username)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TagList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TagList()
|
||||
}
|
||||
}
|
@ -12,24 +12,37 @@ import SwiftyJSON
|
||||
struct TagRow: View {
|
||||
|
||||
@Binding var tag: Tag
|
||||
@State private var showingNetworkError = false
|
||||
|
||||
var body: some View {
|
||||
NavigationLink(destination: TagView(tag: $tag)){
|
||||
HStack {
|
||||
Text(tag.name)
|
||||
.contextMenu {
|
||||
|
||||
// run force touch
|
||||
if tag.count > 0 {
|
||||
Spacer()
|
||||
Text("\(tag.count)")
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}.contextMenu {
|
||||
Button(action: {
|
||||
let api = TagApi.runTag(tag_id: self.tag.tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
RequestBuilder.buildRequest(apiRequest: api)
|
||||
.validate()
|
||||
.responseJSON{ response in
|
||||
switch response.result {
|
||||
case .success:
|
||||
break
|
||||
case .failure:
|
||||
self.showingNetworkError = true
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text("Refresh")
|
||||
Image(systemName: "arrow.clockwise.circle")
|
||||
}
|
||||
}
|
||||
}.alert(isPresented: $showingNetworkError) {
|
||||
Alert(title: Text("Network Error"),
|
||||
message: Text("Could not refresh tag"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ struct TagView: View {
|
||||
.foregroundColor(Color.gray)
|
||||
}
|
||||
HStack {
|
||||
Text("User Total")
|
||||
Text("Total")
|
||||
Spacer()
|
||||
Text("\(self.tag.total_user_scrobbles)")
|
||||
.font(.title)
|
||||
|
Loading…
Reference in New Issue
Block a user