tweaking settings, splitting spotify and managed input lists
This commit is contained in:
parent
761a755973
commit
d73ec449cf
@ -9,6 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
A10C8D29281302050018AE12 /* ToastUI in Frameworks */ = {isa = PBXBuildFile; productRef = A10C8D28281302050018AE12 /* ToastUI */; };
|
||||
A11AC70628A188AE00645043 /* AuthApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11AC70528A188AE00645043 /* AuthApi.swift */; };
|
||||
A13C54972928FD7C0034F233 /* ManagedInputList.swift in Sources */ = {isa = PBXBuildFile; fileRef = A13C54962928FD7C0034F233 /* ManagedInputList.swift */; };
|
||||
A1AF726F28A84F7D00D317C9 /* AdminApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1AF726E28A84F7D00D317C9 /* AdminApi.swift */; };
|
||||
A1AF727128A850AE00D317C9 /* UsersList.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1AF727028A850AE00D317C9 /* UsersList.swift */; };
|
||||
A1AF727328A9062600D317C9 /* UserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1AF727228A9062600D317C9 /* UserView.swift */; };
|
||||
@ -24,7 +25,7 @@
|
||||
E97AF46023FC85D600635494 /* PlaylistApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = E97AF45F23FC85D600635494 /* PlaylistApi.swift */; };
|
||||
E97AF46423FD4EEF00635494 /* LiveUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = E97AF46323FD4EEF00635494 /* LiveUser.swift */; };
|
||||
E97AF46723FD650800635494 /* AddPlaylistSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = E97AF46623FD650800635494 /* AddPlaylistSheet.swift */; };
|
||||
E97AF46923FD9E1B00635494 /* PlaylistInputList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E97AF46823FD9E1B00635494 /* PlaylistInputList.swift */; };
|
||||
E97AF46923FD9E1B00635494 /* SpotInputList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E97AF46823FD9E1B00635494 /* SpotInputList.swift */; };
|
||||
E98254BD23F9B7A90056D9D3 /* Playlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98254BC23F9B7A90056D9D3 /* Playlist.swift */; };
|
||||
E98254C223F9FFF90056D9D3 /* PlaylistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98254C123F9FFF90056D9D3 /* PlaylistView.swift */; };
|
||||
E98254CA23FA26600056D9D3 /* PlaylistRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98254C923FA26600056D9D3 /* PlaylistRow.swift */; };
|
||||
@ -68,6 +69,7 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
A11AC70528A188AE00645043 /* AuthApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthApi.swift; sourceTree = "<group>"; };
|
||||
A13C54962928FD7C0034F233 /* ManagedInputList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedInputList.swift; sourceTree = "<group>"; };
|
||||
A146915A28118F940052999D /* Mixonomer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mixonomer.entitlements; sourceTree = "<group>"; };
|
||||
A1AF726E28A84F7D00D317C9 /* AdminApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminApi.swift; sourceTree = "<group>"; };
|
||||
A1AF727028A850AE00D317C9 /* UsersList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersList.swift; sourceTree = "<group>"; };
|
||||
@ -81,7 +83,7 @@
|
||||
E97AF45F23FC85D600635494 /* PlaylistApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistApi.swift; sourceTree = "<group>"; };
|
||||
E97AF46323FD4EEF00635494 /* LiveUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveUser.swift; sourceTree = "<group>"; };
|
||||
E97AF46623FD650800635494 /* AddPlaylistSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddPlaylistSheet.swift; sourceTree = "<group>"; };
|
||||
E97AF46823FD9E1B00635494 /* PlaylistInputList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistInputList.swift; sourceTree = "<group>"; };
|
||||
E97AF46823FD9E1B00635494 /* SpotInputList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpotInputList.swift; sourceTree = "<group>"; };
|
||||
E98254BC23F9B7A90056D9D3 /* Playlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Playlist.swift; sourceTree = "<group>"; };
|
||||
E98254C123F9FFF90056D9D3 /* PlaylistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistView.swift; sourceTree = "<group>"; };
|
||||
E98254C923FA26600056D9D3 /* PlaylistRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistRow.swift; sourceTree = "<group>"; };
|
||||
@ -205,8 +207,9 @@
|
||||
E98254C123F9FFF90056D9D3 /* PlaylistView.swift */,
|
||||
E98254C923FA26600056D9D3 /* PlaylistRow.swift */,
|
||||
E97AF46623FD650800635494 /* AddPlaylistSheet.swift */,
|
||||
E97AF46823FD9E1B00635494 /* PlaylistInputList.swift */,
|
||||
E97AF46823FD9E1B00635494 /* SpotInputList.swift */,
|
||||
E9CCD5BA2454C57300B5CD6C /* PlaylistList.swift */,
|
||||
A13C54962928FD7C0034F233 /* ManagedInputList.swift */,
|
||||
);
|
||||
path = Playlist;
|
||||
sourceTree = "<group>";
|
||||
@ -459,6 +462,7 @@
|
||||
A1AF727128A850AE00D317C9 /* UsersList.swift in Sources */,
|
||||
E9EA690F23F9A5430012C3E8 /* AppSkeleton.swift in Sources */,
|
||||
E98254BD23F9B7A90056D9D3 /* Playlist.swift in Sources */,
|
||||
A13C54972928FD7C0034F233 /* ManagedInputList.swift in Sources */,
|
||||
E97AF46723FD650800635494 /* AddPlaylistSheet.swift in Sources */,
|
||||
E971F8B9245462D500B543B6 /* Router.swift in Sources */,
|
||||
E98254C223F9FFF90056D9D3 /* PlaylistView.swift in Sources */,
|
||||
@ -466,7 +470,7 @@
|
||||
E97AF45623FC4E7800635494 /* User.swift in Sources */,
|
||||
E98254D023FB00B60056D9D3 /* LoginScreen.swift in Sources */,
|
||||
E9E30C2623FEA4F000574EEF /* TagApi.swift in Sources */,
|
||||
E97AF46923FD9E1B00635494 /* PlaylistInputList.swift in Sources */,
|
||||
E97AF46923FD9E1B00635494 /* SpotInputList.swift in Sources */,
|
||||
E97AF45B23FC748D00635494 /* UserApi.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -45,9 +45,7 @@ class LiveUser: ObservableObject {
|
||||
|
||||
func lastfm_connected() -> Bool {
|
||||
if let username = user?.lastfm_username {
|
||||
if username.count > 0 {
|
||||
return true
|
||||
}
|
||||
return username.count > 0
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -26,6 +26,11 @@ public enum PlaylistApi {
|
||||
case newPlaylist(name: String, type: PlaylistType)
|
||||
case getPlaylist(name: String)
|
||||
case refreshStats(name: String)
|
||||
|
||||
case addPart(name: String, subject: String)
|
||||
case removePart(name: String, subject: String)
|
||||
case addRef(name: String, subject: String)
|
||||
case removeRef(name: String, subject: String)
|
||||
}
|
||||
|
||||
extension PlaylistApi: ApiRequest {
|
||||
@ -49,6 +54,8 @@ extension PlaylistApi: ApiRequest {
|
||||
return "api/playlist"
|
||||
case .refreshStats:
|
||||
return "api/spotfm/playlist/refresh"
|
||||
case .addPart, .removePart, .addRef, .removeRef:
|
||||
return "api/playlist"
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +75,8 @@ extension PlaylistApi: ApiRequest {
|
||||
return .get
|
||||
case .refreshStats:
|
||||
return .get
|
||||
case .addPart, .removePart, .addRef, .removeRef:
|
||||
return .post
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +98,14 @@ extension PlaylistApi: ApiRequest {
|
||||
return JSON(["name": name])
|
||||
case .refreshStats(let name):
|
||||
return JSON(["name": name])
|
||||
case .addPart(let name, let subject):
|
||||
return JSON(["name": name, "subject": subject])
|
||||
case .removePart(let name, let subject):
|
||||
return JSON(["name": name, "subject": subject])
|
||||
case .addRef(let name, let subject):
|
||||
return JSON(["name": name, "subject": subject])
|
||||
case .removeRef(let name, let subject):
|
||||
return JSON(["name": name, "subject": subject])
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +125,8 @@ extension PlaylistApi: ApiRequest {
|
||||
return URLEncodedFormParameterEncoder()
|
||||
case .refreshStats:
|
||||
return URLEncodedFormParameterEncoder()
|
||||
case .addPart, .removePart, .addRef, .removeRef:
|
||||
return JSONParameterEncoder.default
|
||||
}
|
||||
}
|
||||
|
||||
|
53
Mixonomer/Views/Playlist/ManagedInputList.swift
Normal file
53
Mixonomer/Views/Playlist/ManagedInputList.swift
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// ManagedInputList.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 19/11/2022.
|
||||
// Copyright © 2022 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ManagedInputList: View {
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
|
||||
@Binding var playlist: Playlist
|
||||
@Binding var names: [String]
|
||||
|
||||
@State var addName: String = ""
|
||||
|
||||
@State private var addAlertShowing = false
|
||||
|
||||
init(names: Binding<[String]>, playlist: Binding<Playlist>){
|
||||
self._names = names
|
||||
self._playlist = playlist
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List{
|
||||
Section(header: Image(systemName: "music.note")){ // Weird? added empty header as list renders with space for header then jumps up, not nice
|
||||
if self.names.count > 0 {
|
||||
ForEach(self.names, id: \.self){ name in
|
||||
Text(name)
|
||||
}
|
||||
}else {
|
||||
HStack {
|
||||
Text("No Playlists")
|
||||
.multilineTextAlignment(.center)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .id(UUID())
|
||||
.navigationBarTitle("Managed Playlists")
|
||||
}
|
||||
}
|
||||
|
||||
struct ManagedInputList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ManagedInputList(names: .constant([
|
||||
"name"
|
||||
]), playlist: .constant(Playlist(name: "Name")))
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// PlaylistInputList.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 19/02/2020.
|
||||
// Copyright © 2020 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct Name: Identifiable, Hashable {
|
||||
var id = UUID()
|
||||
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, type: PlaylistInputType){
|
||||
self.nameType = nameType
|
||||
self._names = names
|
||||
self.type = type
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List{
|
||||
Section(header: Image(systemName: "music.note")){ // Weird? added empty header as list renders with space for header then jumps up, not nice
|
||||
if self.names.count > 0 {
|
||||
ForEach(self.names, id: \.self){ name in
|
||||
Text(name)
|
||||
}
|
||||
}else {
|
||||
HStack {
|
||||
Text("No Playlists")
|
||||
.multilineTextAlignment(.center)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .id(UUID())
|
||||
.navigationBarTitle(nameType)
|
||||
// .navigationBarItems(trailing:
|
||||
// Button(
|
||||
// action: {
|
||||
//
|
||||
// },
|
||||
// label: { Image(systemName: "plus.circle") }
|
||||
// )
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
struct PlaylistInputList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
PlaylistInputList(names: .constant([
|
||||
"name"
|
||||
]), nameType: "Spotify Playlists", type: .MixonomerPlaylists)
|
||||
}
|
||||
}
|
@ -187,7 +187,7 @@ struct PlaylistView: View {
|
||||
}
|
||||
}
|
||||
Section(header: Text("Inputs")){
|
||||
NavigationLink(destination: PlaylistInputList(names: self.$playlist.playlist_references, nameType: "Managed Playlists", type: .MixonomerPlaylists)) {
|
||||
NavigationLink(destination: ManagedInputList(names: self.$playlist.playlist_references, playlist: self.$playlist)) {
|
||||
HStack {
|
||||
Text("Managed Playlists")
|
||||
Spacer()
|
||||
@ -196,7 +196,7 @@ struct PlaylistView: View {
|
||||
}
|
||||
}
|
||||
|
||||
NavigationLink(destination: PlaylistInputList(names: self.$playlist.parts, nameType: "Spotify Playlists", type: .SpotifyPlaylists)) {
|
||||
NavigationLink(destination: SpotInputList(names: self.$playlist.parts, playlist: self.$playlist)) {
|
||||
HStack {
|
||||
Text("Spotify Playlists")
|
||||
Spacer()
|
||||
|
114
Mixonomer/Views/Playlist/SpotInputList.swift
Normal file
114
Mixonomer/Views/Playlist/SpotInputList.swift
Normal file
@ -0,0 +1,114 @@
|
||||
//
|
||||
// PlaylistInputList.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 19/02/2020.
|
||||
// Copyright © 2020 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import ToastUI
|
||||
|
||||
struct Name: Identifiable, Hashable {
|
||||
var id = UUID()
|
||||
var name: String
|
||||
}
|
||||
|
||||
struct SpotInputList: View {
|
||||
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
|
||||
@Binding var playlist: Playlist
|
||||
@Binding var names: [String]
|
||||
|
||||
@State var addName: String = ""
|
||||
|
||||
@State private var addAlertShowing = false
|
||||
|
||||
@State private var showingToast = false
|
||||
@State private var toastText = ""
|
||||
@State private var toastSuccess = true
|
||||
|
||||
init(names: Binding<[String]>, playlist: Binding<Playlist>){
|
||||
self._names = names
|
||||
self._playlist = playlist
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List{
|
||||
Section(header: Image(systemName: "music.note")){ // Weird? added empty header as list renders with space for header then jumps up, not nice
|
||||
if self.names.count > 0 {
|
||||
ForEach(self.names, id: \.self){ name in
|
||||
Text(name)
|
||||
}
|
||||
}else {
|
||||
HStack {
|
||||
Text("No Playlists")
|
||||
.multilineTextAlignment(.center)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .id(UUID())
|
||||
.navigationBarTitle("Spotify Playlists")
|
||||
.navigationBarItems(trailing:
|
||||
Button(
|
||||
action: {
|
||||
addAlertShowing = true
|
||||
},
|
||||
label: { Image(systemName: "plus.circle") }
|
||||
)
|
||||
.alert("Add", isPresented: $addAlertShowing, actions: {
|
||||
TextField("Playlist Name", text: $addName)
|
||||
Button("Add") {
|
||||
|
||||
let api = PlaylistApi.addPart(name: playlist.name, subject: addName)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
playlist.parts.append(addName)
|
||||
|
||||
toastText = "Playlist Added"
|
||||
toastSuccess = true
|
||||
showingToast = true
|
||||
}
|
||||
else {
|
||||
print("Failed to add playlist: \(response.response?.statusCode ?? 0)")
|
||||
toastText = "Failed to add playlist"
|
||||
toastSuccess = false
|
||||
showingToast = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Button("Cancel", role: .cancel) {
|
||||
addAlertShowing = false
|
||||
}
|
||||
}, message: {
|
||||
Text("Enter a playlist name")
|
||||
|
||||
})
|
||||
)
|
||||
.toast(isPresented: $showingToast, dismissAfter: 1.0){
|
||||
|
||||
if toastSuccess {
|
||||
ToastView(toastText)
|
||||
.toastViewStyle(.success)
|
||||
}
|
||||
else {
|
||||
ToastView(toastText)
|
||||
.toastViewStyle(.failure)
|
||||
}
|
||||
}
|
||||
.toastDimmedBackground(false)
|
||||
}
|
||||
}
|
||||
|
||||
struct PlaylistInputList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SpotInputList(names: .constant([
|
||||
"name"
|
||||
]), playlist: .constant(Playlist(name: "Name")))
|
||||
}
|
||||
}
|
@ -19,8 +19,8 @@ struct SettingsList: View {
|
||||
|
||||
let spotify_link_bind = Binding<Bool>(get: { liveUser.user?.spotify_linked ?? false},
|
||||
set: { newVal in liveUser.user?.spotify_linked = newVal })
|
||||
let lastfm_bind = Binding<String>(get: { liveUser.user?.lastfm_username ?? ""},
|
||||
set: { newVal in liveUser.user?.lastfm_username = newVal })
|
||||
// let lastfm_bind = Binding<String>(get: { liveUser.user?.lastfm_username ?? ""},
|
||||
// set: { newVal in liveUser.user?.lastfm_username = newVal })
|
||||
|
||||
return NavigationView {
|
||||
List{
|
||||
@ -46,16 +46,22 @@ struct SettingsList: View {
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Spotify")) {
|
||||
Section(header: Text("Integrations")) {
|
||||
Toggle(isOn: spotify_link_bind) {
|
||||
Text("Account Link")
|
||||
Text("Spotify Link")
|
||||
}
|
||||
.disabled(true)
|
||||
|
||||
// NavigationLink("Last.fm Username") {
|
||||
// List{
|
||||
// TextField("Username", text: lastfm_bind)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
Section(header: Text("Last.fm")) {
|
||||
TextField("Last.fm Username", text: lastfm_bind)
|
||||
}
|
||||
// Section(header: Text("Last.fm")) {
|
||||
// TextField("Last.fm Username", text: lastfm_bind)
|
||||
// }
|
||||
|
||||
Section {
|
||||
Button(action: {
|
||||
@ -65,7 +71,6 @@ struct SettingsList: View {
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
.alert("Delete Account", isPresented: $deleteAlertShowing, actions: {
|
||||
Text("This will irreversibly delete all of your data, are you sure?")
|
||||
Button("Delete", role: .destructive) {
|
||||
|
||||
let api = UserApi.deleteUser
|
||||
@ -81,12 +86,8 @@ struct SettingsList: View {
|
||||
}
|
||||
|
||||
}
|
||||
Button("Cancel", role: .cancel) {
|
||||
deleteAlertShowing = false
|
||||
}
|
||||
}, message: {
|
||||
Text("This is irreversible, are you sure you want to delete your account?")
|
||||
|
||||
})
|
||||
}
|
||||
Section(
|
||||
|
@ -1,8 +1,6 @@
|
||||
# Mixonomer iOS
|
||||
|
||||
iOS client for [Mixonomer](https://mixonomer.sarsoo.xyz) ([Source](https://github.com/sarsoo/Mixonomer)), using it to learn swift.
|
||||
|
||||
Using SwiftUI for the main app UI. Hanging SwiftUI on a hosting controller for log in/register.
|
||||
iOS client for [Mixonomer](https://mixonomer.sarsoo.xyz) ([Source](https://github.com/sarsoo/Mixonomer)), using it to learn swift and SwiftUI.
|
||||
|
||||
Using Alamofire and SwiftyJSON for network requests.
|
||||
|
||||
|
BIN
res/Splashscreen.png
Normal file
BIN
res/Splashscreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Loading…
Reference in New Issue
Block a user