initial notifications support
This commit is contained in:
parent
a3b1a67b5b
commit
8f103fab3e
@ -10,6 +10,10 @@
|
||||
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 */; };
|
||||
A15D257A293421350049055E /* StaticNotif.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15D2579293421350049055E /* StaticNotif.swift */; };
|
||||
A15D257C293425390049055E /* NotificationsControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15D257B293425390049055E /* NotificationsControls.swift */; };
|
||||
A15D257E29342E4F0049055E /* APNSHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15D257D29342E4F0049055E /* APNSHandler.swift */; };
|
||||
A15D258029342EF50049055E /* NetworkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15D257F29342EF50049055E /* NetworkHelper.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 */; };
|
||||
@ -71,6 +75,10 @@
|
||||
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>"; };
|
||||
A15D2579293421350049055E /* StaticNotif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticNotif.swift; sourceTree = "<group>"; };
|
||||
A15D257B293425390049055E /* NotificationsControls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsControls.swift; sourceTree = "<group>"; };
|
||||
A15D257D29342E4F0049055E /* APNSHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSHandler.swift; sourceTree = "<group>"; };
|
||||
A15D257F29342EF50049055E /* NetworkHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkHelper.swift; 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>"; };
|
||||
A1AF727228A9062600D317C9 /* UserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserView.swift; sourceTree = "<group>"; };
|
||||
@ -143,6 +151,15 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
A15D2578293421250049055E /* Notifications */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A15D2579293421350049055E /* StaticNotif.swift */,
|
||||
A15D257D29342E4F0049055E /* APNSHandler.swift */,
|
||||
);
|
||||
path = Notifications;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A1DBCDA428A5184D002CF730 /* Admin */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -171,9 +188,10 @@
|
||||
E97AF45F23FC85D600635494 /* PlaylistApi.swift */,
|
||||
E97AF45A23FC748D00635494 /* UserApi.swift */,
|
||||
E9E30C2523FEA4EF00574EEF /* TagApi.swift */,
|
||||
E906F7F32414019C004E1E31 /* NetworkPersister.swift */,
|
||||
A11AC70528A188AE00645043 /* AuthApi.swift */,
|
||||
A1AF726E28A84F7D00D317C9 /* AdminApi.swift */,
|
||||
E906F7F32414019C004E1E31 /* NetworkPersister.swift */,
|
||||
A15D257F29342EF50049055E /* NetworkHelper.swift */,
|
||||
);
|
||||
path = Network;
|
||||
sourceTree = "<group>";
|
||||
@ -230,6 +248,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E9E30C3223FF255C00574EEF /* SettingsList.swift */,
|
||||
A15D257B293425390049055E /* NotificationsControls.swift */,
|
||||
);
|
||||
path = Settings;
|
||||
sourceTree = "<group>";
|
||||
@ -257,6 +276,7 @@
|
||||
E9EA690923F9A5430012C3E8 /* Mixonomer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A15D2578293421250049055E /* Notifications */,
|
||||
A146915A28118F940052999D /* Mixonomer.entitlements */,
|
||||
E98254C623FA25280056D9D3 /* Application */,
|
||||
E9EA691023F9A54A0012C3E8 /* Assets.xcassets */,
|
||||
@ -448,6 +468,7 @@
|
||||
E98254CA23FA26600056D9D3 /* PlaylistRow.swift in Sources */,
|
||||
E9EA690B23F9A5430012C3E8 /* AppDelegate.swift in Sources */,
|
||||
E906F7F42414019C004E1E31 /* NetworkPersister.swift in Sources */,
|
||||
A15D258029342EF50049055E /* NetworkHelper.swift in Sources */,
|
||||
A1AF727328A9062600D317C9 /* UserView.swift in Sources */,
|
||||
E9E30C3323FF255C00574EEF /* SettingsList.swift in Sources */,
|
||||
E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */,
|
||||
@ -459,8 +480,10 @@
|
||||
E97AF46023FC85D600635494 /* PlaylistApi.swift in Sources */,
|
||||
A11AC70628A188AE00645043 /* AuthApi.swift in Sources */,
|
||||
A1AF726F28A84F7D00D317C9 /* AdminApi.swift in Sources */,
|
||||
A15D257E29342E4F0049055E /* APNSHandler.swift in Sources */,
|
||||
A1AF727128A850AE00D317C9 /* UsersList.swift in Sources */,
|
||||
E9EA690F23F9A5430012C3E8 /* AppSkeleton.swift in Sources */,
|
||||
A15D257A293421350049055E /* StaticNotif.swift in Sources */,
|
||||
E98254BD23F9B7A90056D9D3 /* Playlist.swift in Sources */,
|
||||
A13C54972928FD7C0034F233 /* ManagedInputList.swift in Sources */,
|
||||
E97AF46723FD650800635494 /* AddPlaylistSheet.swift in Sources */,
|
||||
@ -471,6 +494,7 @@
|
||||
E98254D023FB00B60056D9D3 /* LoginScreen.swift in Sources */,
|
||||
E9E30C2623FEA4F000574EEF /* TagApi.swift in Sources */,
|
||||
E97AF46923FD9E1B00635494 /* SpotInputList.swift in Sources */,
|
||||
A15D257C293425390049055E /* NotificationsControls.swift in Sources */,
|
||||
E97AF45B23FC748D00635494 /* UserApi.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -53,7 +53,7 @@
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "MTOOLS_SERVER"
|
||||
value = "http://127.0.0.1:5000/"
|
||||
value = "http://127.0.0.1:8080/"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
|
@ -15,6 +15,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
UIApplication.shared.registerForRemoteNotifications()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -31,8 +32,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication,
|
||||
didRegisterForRemoteNotificationsWithDeviceToken
|
||||
deviceToken: Data) {
|
||||
|
||||
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
|
||||
|
||||
StaticNotif.token = token
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication,
|
||||
didFailToRegisterForRemoteNotificationsWithError
|
||||
error: Error) {
|
||||
// Try again later.
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication,
|
||||
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
|
||||
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
||||
completionHandler(.noData)
|
||||
}
|
||||
}
|
||||
|
||||
extension Logger {
|
||||
|
@ -150,6 +150,66 @@
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"filename" : "16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "64.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "1024.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "48.png",
|
||||
"idiom" : "watch",
|
||||
@ -225,6 +285,13 @@
|
||||
"size" : "51x51",
|
||||
"subtype" : "45mm"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"role" : "appLauncher",
|
||||
"scale" : "2x",
|
||||
"size" : "54x54",
|
||||
"subtype" : "49mm"
|
||||
},
|
||||
{
|
||||
"filename" : "172.png",
|
||||
"idiom" : "watch",
|
||||
@ -256,71 +323,18 @@
|
||||
"size" : "117x117",
|
||||
"subtype" : "45mm"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"role" : "quickLook",
|
||||
"scale" : "2x",
|
||||
"size" : "129x129",
|
||||
"subtype" : "49mm"
|
||||
},
|
||||
{
|
||||
"filename" : "1024.png",
|
||||
"idiom" : "watch-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"filename" : "16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "64.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "1024.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
@ -43,6 +43,10 @@
|
||||
</dict>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
|
@ -2,6 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
|
@ -11,13 +11,14 @@ import Alamofire
|
||||
import SwiftyJSON
|
||||
import KeychainAccess
|
||||
import OSLog
|
||||
import UserNotifications
|
||||
|
||||
class LiveUser: ObservableObject {
|
||||
|
||||
@Published var playlists: [Playlist]
|
||||
@Published var tags: [Tag]
|
||||
@Published var username: String
|
||||
@Published var user: User?
|
||||
@Published var user: User
|
||||
|
||||
@Published var loggedIn: Bool {
|
||||
didSet {
|
||||
@ -25,6 +26,27 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func requestAPNSPerms(){
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
|
||||
|
||||
if error != nil {
|
||||
self.handleAPNSFailure()
|
||||
}
|
||||
else {
|
||||
|
||||
// load token from static var and pass to backend server
|
||||
APNSHandler.pass_token_to_backend(onFailure: {
|
||||
self.handleAPNSFailure()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleAPNSFailure(){
|
||||
Logger.sys.debug("failed to get APNS token")
|
||||
}
|
||||
|
||||
@Published var isRefreshingUser = false
|
||||
@Published var isRefreshingPlaylists = false
|
||||
@Published var isRefreshingTags = false
|
||||
@ -34,6 +56,7 @@ class LiveUser: ObservableObject {
|
||||
self.tags = tags
|
||||
self.username = username
|
||||
self.loggedIn = loggedIn
|
||||
self.user = User.get_null_user()
|
||||
}
|
||||
|
||||
init(playlists: [Playlist], tags: [Tag], username: String, loggedIn: Bool, user: User) {
|
||||
@ -45,11 +68,7 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
|
||||
func lastfm_connected() -> Bool {
|
||||
if let username = user?.lastfm_username {
|
||||
return username.count > 0
|
||||
}
|
||||
|
||||
return false
|
||||
return username.count > 0
|
||||
}
|
||||
|
||||
func logout() {
|
||||
@ -64,7 +83,7 @@ class LiveUser: ObservableObject {
|
||||
playlists.removeAll()
|
||||
tags.removeAll()
|
||||
username = ""
|
||||
user = nil
|
||||
user = User.get_null_user()
|
||||
|
||||
UserDefaults.standard.removeObject(forKey: "playlists")
|
||||
UserDefaults.standard.removeObject(forKey: "tags")
|
||||
@ -224,27 +243,9 @@ class LiveUser: ObservableObject {
|
||||
}
|
||||
|
||||
func check_network_response(response: AFDataResponse<Any>) -> Bool {
|
||||
|
||||
if let statusCode = response.response?.statusCode {
|
||||
switch statusCode {
|
||||
case 401: // token has expired
|
||||
Logger.sys.info("token expired, logging user out")
|
||||
self.logout()
|
||||
return false
|
||||
case 400..<500:
|
||||
Logger.net.error("client fault \(statusCode)")
|
||||
return false
|
||||
case 500..<600:
|
||||
Logger.net.warning("server fault \(statusCode)")
|
||||
return false
|
||||
case _: // 200 -> Success
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Logger.net.error("live user failed to access status code to check")
|
||||
|
||||
return false
|
||||
return NetworkHelper.check_network_response(response: response, onTokenFail: {
|
||||
self.logout()
|
||||
})
|
||||
}
|
||||
|
||||
func load_user_defaults() -> LiveUser {
|
||||
@ -277,4 +278,12 @@ class LiveUser: ObservableObject {
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
static func get_preview_user() -> LiveUser {
|
||||
return LiveUser(playlists: [], tags: [], username: "user", loggedIn: false)
|
||||
}
|
||||
|
||||
static func get_preview_user_with_user() -> LiveUser {
|
||||
return LiveUser(playlists: [], tags: [], username: "user", loggedIn: false, user: User())
|
||||
}
|
||||
}
|
||||
|
@ -30,28 +30,28 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
|
||||
self.updatePlaylist(updates: JSON(["include_recommendations": self.include_recommendations]))
|
||||
}
|
||||
}
|
||||
@Published var recommendation_sample: Int{
|
||||
@Published var recommendation_sample: Int {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["recommendation_sample": self.recommendation_sample]))
|
||||
}
|
||||
}
|
||||
@Published var include_library_tracks: Bool{
|
||||
@Published var include_library_tracks: Bool {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["include_library_tracks": self.include_library_tracks]))
|
||||
}
|
||||
}
|
||||
|
||||
@Published var parts: Array<String>{
|
||||
@Published var parts: Array<String> {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["parts": self.parts]))
|
||||
}
|
||||
}
|
||||
@Published var playlist_references: Array<String>{
|
||||
@Published var playlist_references: Array<String> {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["playlist_references": self.playlist_references]))
|
||||
}
|
||||
}
|
||||
@Published var shuffle: Bool{
|
||||
@Published var shuffle: Bool {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["shuffle": self.shuffle]))
|
||||
}
|
||||
@ -88,45 +88,45 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
|
||||
|
||||
@Published var lastfm_stat_last_refresh: String?
|
||||
|
||||
@Published var add_last_month: Bool{
|
||||
@Published var add_last_month: Bool {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["add_last_month": self.add_last_month]))
|
||||
}
|
||||
}
|
||||
@Published var add_this_month: Bool{
|
||||
@Published var add_this_month: Bool {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["add_this_month": self.add_this_month]))
|
||||
}
|
||||
}
|
||||
@Published var day_boundary: Int{
|
||||
@Published var day_boundary: Int {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["day_boundary": self.day_boundary]))
|
||||
}
|
||||
}
|
||||
|
||||
@Published var chart_range: LastFmRange{
|
||||
@Published var chart_range: LastFmRange {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["chart_range": self.chart_range.rawValue]))
|
||||
}
|
||||
}
|
||||
@Published var chart_limit: Int{
|
||||
@Published var chart_limit: Int {
|
||||
didSet {
|
||||
self.updatePlaylist(updates: JSON(["chart_range": self.chart_range.rawValue]))
|
||||
self.updatePlaylist(updates: JSON(["chart_limit": self.chart_limit]))
|
||||
}
|
||||
}
|
||||
|
||||
func updatePlaylist(updates: JSON) {
|
||||
let api = PlaylistApi.updatePlaylist(name: self.name, updates: updates)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
switch response.response?.statusCode {
|
||||
case 200, 201:
|
||||
break
|
||||
case _:
|
||||
Logger.net.error("error: \(self.name), \(updates)")
|
||||
let api = PlaylistApi.updatePlaylist(name: self.name, updates: updates)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
switch response.response?.statusCode {
|
||||
case 200, 201:
|
||||
break
|
||||
case _:
|
||||
Logger.net.error("error: \(self.name), \(updates)")
|
||||
}
|
||||
}
|
||||
//TODO: do better error checking
|
||||
}
|
||||
//TODO: do better error checking
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name
|
||||
|
@ -15,7 +15,7 @@ enum UserType: String, Decodable {
|
||||
case admin = "admin"
|
||||
}
|
||||
|
||||
class User: Identifiable, Decodable {
|
||||
class User: Identifiable, Decodable, ObservableObject {
|
||||
|
||||
//MARK: Properties
|
||||
|
||||
@ -30,7 +30,29 @@ class User: Identifiable, Decodable {
|
||||
var last_refreshed: String
|
||||
|
||||
var spotify_linked: Bool
|
||||
@Published var lastfm_username: String? {
|
||||
|
||||
@Published var notify: Bool {
|
||||
didSet {
|
||||
self.updateUser(updates: JSON(["notify": self.notify]))
|
||||
}
|
||||
}
|
||||
@Published var notify_playlist_updates: Bool {
|
||||
didSet {
|
||||
self.updateUser(updates: JSON(["notify_playlist_updates": self.notify_playlist_updates]))
|
||||
}
|
||||
}
|
||||
@Published var notify_tag_updates: Bool {
|
||||
didSet {
|
||||
self.updateUser(updates: JSON(["notify_tag_updates": self.notify_tag_updates]))
|
||||
}
|
||||
}
|
||||
@Published var notify_admins: Bool {
|
||||
didSet {
|
||||
self.updateUser(updates: JSON(["notify_admins": self.notify_admins]))
|
||||
}
|
||||
}
|
||||
|
||||
@Published var lastfm_username: String {
|
||||
didSet {
|
||||
self.updateUser(updates: JSON(["lastfm_username": self.lastfm_username]))
|
||||
}
|
||||
@ -48,7 +70,12 @@ class User: Identifiable, Decodable {
|
||||
last_keygen: String = "",
|
||||
last_refreshed: String = "",
|
||||
spotify_linked: Bool = true,
|
||||
lastfm_username: String? = nil){
|
||||
lastfm_username: String = "",
|
||||
|
||||
notify: Bool = false,
|
||||
notify_playlist_updates: Bool = false,
|
||||
notify_tag_updates: Bool = false,
|
||||
notify_admins: Bool = false){
|
||||
|
||||
self.username = username
|
||||
self.email = email
|
||||
@ -61,19 +88,21 @@ class User: Identifiable, Decodable {
|
||||
self.last_refreshed = last_refreshed
|
||||
self.spotify_linked = spotify_linked
|
||||
self.lastfm_username = lastfm_username
|
||||
|
||||
self.notify = notify
|
||||
self.notify_playlist_updates = notify_playlist_updates
|
||||
self.notify_tag_updates = notify_tag_updates
|
||||
self.notify_admins = notify_admins
|
||||
}
|
||||
|
||||
|
||||
func updateUser(updates: JSON) {
|
||||
let api = UserApi.updateUser(updates: updates)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
switch response.response?.statusCode {
|
||||
case 200, 201:
|
||||
break
|
||||
case _:
|
||||
|
||||
if !NetworkHelper.check_network_response(response: response) {
|
||||
Logger.net.error("error while updating user: \(updates)")
|
||||
}
|
||||
}
|
||||
//TODO: do better error checking
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@ -89,6 +118,11 @@ class User: Identifiable, Decodable {
|
||||
|
||||
case spotify_linked
|
||||
case lastfm_username
|
||||
|
||||
case notify
|
||||
case notify_playlist_updates
|
||||
case notify_tag_updates
|
||||
case notify_admins
|
||||
}
|
||||
|
||||
required init(from decoder: Decoder) throws {
|
||||
@ -120,7 +154,31 @@ class User: Identifiable, Decodable {
|
||||
do{
|
||||
lastfm_username = try container.decode(String.self, forKey: .lastfm_username)
|
||||
}catch {
|
||||
lastfm_username = nil
|
||||
lastfm_username = ""
|
||||
}
|
||||
|
||||
do{
|
||||
notify = try container.decode(Bool.self, forKey: .notify)
|
||||
}catch {
|
||||
notify = false
|
||||
}
|
||||
|
||||
do{
|
||||
notify_playlist_updates = try container.decode(Bool.self, forKey: .notify_playlist_updates)
|
||||
}catch {
|
||||
notify_playlist_updates = false
|
||||
}
|
||||
|
||||
do{
|
||||
notify_tag_updates = try container.decode(Bool.self, forKey: .notify_tag_updates)
|
||||
}catch {
|
||||
notify_tag_updates = false
|
||||
}
|
||||
|
||||
do{
|
||||
notify_admins = try container.decode(Bool.self, forKey: .notify_admins)
|
||||
}catch {
|
||||
notify_admins = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,6 +197,15 @@ class User: Identifiable, Decodable {
|
||||
|
||||
try container.encode(self.spotify_linked, forKey: .spotify_linked)
|
||||
try container.encode(self.lastfm_username, forKey: .lastfm_username)
|
||||
|
||||
try container.encode(self.notify, forKey: .notify)
|
||||
try container.encode(self.notify_playlist_updates, forKey: .notify_playlist_updates)
|
||||
try container.encode(self.notify_tag_updates, forKey: .notify_tag_updates)
|
||||
try container.encode(self.notify_admins, forKey: .notify_admins)
|
||||
}
|
||||
|
||||
static func get_null_user() -> User {
|
||||
return User()
|
||||
}
|
||||
}
|
||||
|
||||
|
38
Mixonomer/Network/NetworkHelper.swift
Normal file
38
Mixonomer/Network/NetworkHelper.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// NetworkHelper.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 27/11/2022.
|
||||
// Copyright © 2022 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import OSLog
|
||||
import Alamofire
|
||||
|
||||
class NetworkHelper {
|
||||
|
||||
static func check_network_response(response: AFDataResponse<Any>, onTokenFail: (() -> Void)? = nil) -> Bool {
|
||||
|
||||
if let statusCode = response.response?.statusCode {
|
||||
switch statusCode {
|
||||
case 401: // token has expired
|
||||
Logger.sys.info("token expired, logging user out")
|
||||
onTokenFail?()
|
||||
return false
|
||||
case 400..<500:
|
||||
Logger.net.error("client fault \(statusCode)")
|
||||
return false
|
||||
case 500..<600:
|
||||
Logger.net.warning("server fault \(statusCode)")
|
||||
return false
|
||||
case _: // 200 -> Success
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Logger.net.error("failed to access network status code to validate")
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
@ -15,6 +15,11 @@ public enum UserApi {
|
||||
case getUser
|
||||
case updateUser(updates: JSON)
|
||||
case deleteUser
|
||||
case passAPNSToken(updates: String)
|
||||
case updateNotify(state: Bool)
|
||||
case updateNotifyPlaylist(state: String)
|
||||
case updateNotifyTag(state: String)
|
||||
case updateNotifyAdmin(state: String)
|
||||
}
|
||||
|
||||
extension UserApi: ApiRequest {
|
||||
@ -30,6 +35,10 @@ extension UserApi: ApiRequest {
|
||||
return "api/user"
|
||||
case .deleteUser:
|
||||
return "api/user"
|
||||
case .passAPNSToken:
|
||||
return "api/user"
|
||||
case .updateNotify, .updateNotifyPlaylist, .updateNotifyTag, .updateNotifyAdmin:
|
||||
return "api/user"
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +50,10 @@ extension UserApi: ApiRequest {
|
||||
return .post
|
||||
case .deleteUser:
|
||||
return .delete
|
||||
case .passAPNSToken:
|
||||
return .post
|
||||
case .updateNotify, .updateNotifyPlaylist, .updateNotifyTag, .updateNotifyAdmin:
|
||||
return .post
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +63,16 @@ extension UserApi: ApiRequest {
|
||||
return nil
|
||||
case .updateUser(let updates):
|
||||
return updates
|
||||
case .passAPNSToken(let token):
|
||||
return JSON(["apns_token": token])
|
||||
case .updateNotify(let state):
|
||||
return JSON(["notify": state])
|
||||
case .updateNotifyPlaylist(let state):
|
||||
return JSON(["notify_playlist_updates": state])
|
||||
case .updateNotifyTag(let state):
|
||||
return JSON(["notify_tag_updates": state])
|
||||
case .updateNotifyAdmin(let state):
|
||||
return JSON(["notify_admins": state])
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +80,9 @@ extension UserApi: ApiRequest {
|
||||
switch self {
|
||||
case .getUser, .deleteUser:
|
||||
return nil
|
||||
case .updateUser:
|
||||
case .updateUser, .passAPNSToken:
|
||||
return JSONParameterEncoder.default
|
||||
case .updateNotify, .updateNotifyPlaylist, .updateNotifyTag, .updateNotifyAdmin:
|
||||
return JSONParameterEncoder.default
|
||||
}
|
||||
}
|
||||
@ -70,7 +95,7 @@ extension UserApi: ApiRequest {
|
||||
return ApiRequestDefaults.authMethod
|
||||
}
|
||||
|
||||
static func fromJSON(user: Data) -> User? {
|
||||
static func fromJSON(user: Data) -> User {
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
do {
|
||||
@ -78,11 +103,11 @@ extension UserApi: ApiRequest {
|
||||
return user
|
||||
} catch {
|
||||
Logger.parse.error("error parsing user from json: \(error)")
|
||||
return User.get_null_user()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
static func fromJSON(user: JSON) -> User? {
|
||||
static func fromJSON(user: JSON) -> User {
|
||||
|
||||
let _json = user.rawString()?.data(using: .utf8)
|
||||
|
||||
@ -95,16 +120,16 @@ extension UserApi: ApiRequest {
|
||||
Logger.parse.error("error parsing user from json: \(error)")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return User.get_null_user()
|
||||
}
|
||||
|
||||
static func fromJSON(user: [JSON]) -> [User] {
|
||||
var _users: [User] = []
|
||||
for dict in user {
|
||||
let _iter = self.fromJSON(user: dict)
|
||||
if let returned = _iter {
|
||||
_users.append(returned)
|
||||
}
|
||||
|
||||
_users.append(_iter)
|
||||
}
|
||||
return _users
|
||||
}
|
||||
|
37
Mixonomer/Notifications/APNSHandler.swift
Normal file
37
Mixonomer/Notifications/APNSHandler.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// APNSHandler.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 27/11/2022.
|
||||
// Copyright © 2022 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
class APNSHandler {
|
||||
|
||||
static func pass_token_to_backend(onFailure: (() -> Void)? = nil) {
|
||||
// check if a token is waiting to be handed off
|
||||
if let token = StaticNotif.token {
|
||||
if !StaticNotif.hasDelivered {
|
||||
|
||||
Logger.sys.info("passing off APNS network token")
|
||||
let api = UserApi.passAPNSToken(updates: token)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if NetworkHelper.check_network_response(response: response) {
|
||||
Logger.net.debug("successfully handed off APNS token")
|
||||
StaticNotif.hasDelivered = true
|
||||
} else {
|
||||
Logger.net.error("failed to hand off APNS token: \(response.response?.statusCode ?? 0)")
|
||||
onFailure?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger.sys.debug("no APNS token waiting, skipping network handoff")
|
||||
}
|
||||
}
|
||||
}
|
14
Mixonomer/Notifications/StaticNotif.swift
Normal file
14
Mixonomer/Notifications/StaticNotif.swift
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// StaticNotif.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 27/11/2022.
|
||||
// Copyright © 2022 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class StaticNotif {
|
||||
static var token: String?
|
||||
static var hasDelivered: Bool = false
|
||||
}
|
@ -74,6 +74,6 @@ struct UsersList: View {
|
||||
struct UsersList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
UsersList()
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,6 @@ struct AppSkeleton: View {
|
||||
struct RootView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AppSkeleton()
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -237,11 +237,11 @@ struct LoginScreen_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group{
|
||||
LoginScreen(screenMode: .None)
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
LoginScreen(screenMode: .Login)
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
LoginScreen(screenMode: .Register)
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +112,6 @@ struct AddPlaylistSheet: View {
|
||||
struct AddPlaylistSheet_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AddPlaylistSheet(playlists: .constant([]), username: .constant("username"))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ struct PlaylistList: View {
|
||||
NavigationView {
|
||||
|
||||
List{
|
||||
if liveUser.user?.spotify_linked == false {
|
||||
if liveUser.user.spotify_linked == false {
|
||||
Text("Spotify isn't linked, login to the web client to pair")
|
||||
|
||||
Button(action: {
|
||||
@ -101,9 +101,9 @@ struct PlaylistList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group {
|
||||
PlaylistList()
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
PlaylistList()
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false, user: User()))
|
||||
.environmentObject(LiveUser.get_preview_user_with_user())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,6 @@ struct PlaylistRow_Previews: PreviewProvider {
|
||||
PlaylistView(playlist: .constant(
|
||||
Playlist(name: "playlist name", username: "username")
|
||||
))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ struct PlaylistView_Previews: PreviewProvider {
|
||||
lastfm_stat_artist_percent: 80
|
||||
)
|
||||
))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
PlaylistView(playlist: .constant(
|
||||
Playlist(name: "playlist name",
|
||||
username: "username",
|
||||
@ -375,7 +375,7 @@ struct PlaylistView_Previews: PreviewProvider {
|
||||
lastfm_stat_artist_percent: 80
|
||||
)
|
||||
))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false, user: User()))
|
||||
.environmentObject(LiveUser.get_preview_user_with_user())
|
||||
}
|
||||
|
||||
}
|
||||
|
52
Mixonomer/Views/Settings/NotificationsControls.swift
Normal file
52
Mixonomer/Views/Settings/NotificationsControls.swift
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// NotificationsControls.swift
|
||||
// Mixonomer
|
||||
//
|
||||
// Created by Andy Pack on 27/11/2022.
|
||||
// Copyright © 2022 Sarsoo. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NotificationsControls: View {
|
||||
|
||||
@EnvironmentObject var liveUser: LiveUser
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
Toggle(isOn: self.$liveUser.user.notify) {
|
||||
Text("Enabled")
|
||||
}
|
||||
}
|
||||
Section {
|
||||
Button("Request permission on this device") {
|
||||
self.liveUser.requestAPNSPerms()
|
||||
}
|
||||
}
|
||||
Section {
|
||||
Toggle(isOn: self.$liveUser.user.notify_playlist_updates) {
|
||||
Text("Playlist Updates")
|
||||
}
|
||||
Toggle(isOn: self.$liveUser.user.notify_tag_updates) {
|
||||
Text("Tag Updates")
|
||||
}
|
||||
|
||||
if liveUser.user.type == .admin {
|
||||
Toggle(isOn: self.$liveUser.user.notify_admins) {
|
||||
Text("Admin Updates")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(GroupedListStyle())
|
||||
.navigationBarTitle(Text("Notifications 🔔"))
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationsControls_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NotificationsControls()
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
@ -16,13 +16,7 @@ struct SettingsList: View {
|
||||
@State private var deleteAlertShowing = false
|
||||
|
||||
var body: some 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 })
|
||||
|
||||
return NavigationView {
|
||||
NavigationView {
|
||||
List{
|
||||
Section {
|
||||
Button(action: {
|
||||
@ -47,21 +41,25 @@ struct SettingsList: View {
|
||||
}
|
||||
|
||||
Section(header: Text("Integrations")) {
|
||||
Toggle(isOn: spotify_link_bind) {
|
||||
Toggle(isOn: self.$liveUser.user.spotify_linked) {
|
||||
Text("Spotify Link")
|
||||
}
|
||||
.disabled(true)
|
||||
|
||||
// NavigationLink("Last.fm Username") {
|
||||
// List{
|
||||
// TextField("Username", text: lastfm_bind)
|
||||
// }
|
||||
// }
|
||||
NavigationLink("Last.fm") {
|
||||
List{
|
||||
TextField("Username", text: self.$liveUser.user.lastfm_username)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Section(header: Text("Last.fm")) {
|
||||
// TextField("Last.fm Username", text: lastfm_bind)
|
||||
// }
|
||||
Section {
|
||||
NavigationLink(destination: NotificationsControls()) {
|
||||
HStack {
|
||||
Text("Notifications")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Button(action: {
|
||||
@ -128,6 +126,6 @@ struct SettingsList: View {
|
||||
struct SettingsList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SettingsList()
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,6 @@ struct AddTagSheet: View {
|
||||
struct AddTagSheet_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AddTagSheet(tags: .constant([]), username: .constant("username"))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,6 @@ struct TagList: View {
|
||||
struct TagList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TagList()
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,6 @@ struct TagRow_Previews: PreviewProvider {
|
||||
|
||||
last_updated: "10th Feb")
|
||||
))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
@ -118,32 +118,41 @@ struct TagView: View {
|
||||
}
|
||||
|
||||
func runTag() {
|
||||
|
||||
Logger.net.debug("running tag from view: \(self.tag.name)")
|
||||
|
||||
let api = TagApi.runTag(tag_id: tag.tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
Logger.net.debug("successfully running tag: \(self.tag.name)")
|
||||
} else {
|
||||
|
||||
Logger.net.error("request failed for running tag: \(self.tag.name)")
|
||||
}
|
||||
}
|
||||
//TODO: do better error checking
|
||||
}
|
||||
|
||||
func updateTag(updates: JSON) {
|
||||
|
||||
Logger.net.debug("updating tag from view: \(self.tag.name)")
|
||||
|
||||
let api = TagApi.updateTag(tag_id: tag.tag_id, updates: updates)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
if self.liveUser.check_network_response(response: response) {
|
||||
|
||||
Logger.net.debug("successfully updated tag: \(self.tag.name)")
|
||||
} else {
|
||||
|
||||
Logger.net.error("request failed for updating tag: \(self.tag.name)")
|
||||
}
|
||||
}
|
||||
//TODO: do better error checking
|
||||
}
|
||||
|
||||
func refreshTag() {
|
||||
|
||||
Logger.net.debug("refreshing tag from view: \(self.tag.name)")
|
||||
|
||||
let api = TagApi.getTag(tag_id: self.tag.tag_id)
|
||||
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
|
||||
|
||||
@ -190,6 +199,6 @@ struct TagView_Previews: PreviewProvider {
|
||||
|
||||
last_updated: "10th Feb")
|
||||
))
|
||||
.environmentObject(LiveUser(playlists: [], tags: [], username: "user", loggedIn: false))
|
||||
.environmentObject(LiveUser.get_preview_user())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user