diff --git a/Mixonomer.xcodeproj/project.pbxproj b/Mixonomer.xcodeproj/project.pbxproj index cef3b41..325e828 100644 --- a/Mixonomer.xcodeproj/project.pbxproj +++ b/Mixonomer.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 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 */; }; + A1846C4329449A8800028978 /* LoadingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1846C4229449A8800028978 /* LoadingScreen.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 */; }; @@ -79,6 +80,7 @@ A15D257B293425390049055E /* NotificationsControls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsControls.swift; sourceTree = ""; }; A15D257D29342E4F0049055E /* APNSHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSHandler.swift; sourceTree = ""; }; A15D257F29342EF50049055E /* NetworkHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkHelper.swift; sourceTree = ""; }; + A1846C4229449A8800028978 /* LoadingScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingScreen.swift; sourceTree = ""; }; A1AF726E28A84F7D00D317C9 /* AdminApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminApi.swift; sourceTree = ""; }; A1AF727028A850AE00D317C9 /* UsersList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersList.swift; sourceTree = ""; }; A1AF727228A9062600D317C9 /* UserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserView.swift; sourceTree = ""; }; @@ -205,6 +207,7 @@ E9E30C2E23FEACDE00574EEF /* Playlist */, E9EA690E23F9A5430012C3E8 /* AppSkeleton.swift */, E98254CF23FB00B60056D9D3 /* LoginScreen.swift */, + A1846C4229449A8800028978 /* LoadingScreen.swift */, ); path = Views; sourceTree = ""; @@ -469,6 +472,7 @@ E9EA690B23F9A5430012C3E8 /* AppDelegate.swift in Sources */, E906F7F42414019C004E1E31 /* NetworkPersister.swift in Sources */, A15D258029342EF50049055E /* NetworkHelper.swift in Sources */, + A1846C4329449A8800028978 /* LoadingScreen.swift in Sources */, A1AF727328A9062600D317C9 /* UserView.swift in Sources */, E9E30C3323FF255C00574EEF /* SettingsList.swift in Sources */, E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */, diff --git a/Mixonomer/Model/LiveUser.swift b/Mixonomer/Model/LiveUser.swift index 5b8bb29..a4fc153 100644 --- a/Mixonomer/Model/LiveUser.swift +++ b/Mixonomer/Model/LiveUser.swift @@ -47,6 +47,10 @@ class LiveUser: ObservableObject { Logger.sys.debug("failed to get APNS token") } + @Published var isInitiallyRefreshingUser = true + @Published var isInitiallyRefreshingPlaylists = true + @Published var isInitiallyRefreshingTags = true + @Published var isRefreshingUser = false @Published var isRefreshingPlaylists = false @Published var isRefreshingTags = false @@ -128,6 +132,7 @@ class LiveUser: ObservableObject { self.user = UserApi.fromJSON(user: json) self.isRefreshingUser = false + self.isInitiallyRefreshingUser = false if let success = onSuccess { Logger.sys.debug("successfully refreshed user") @@ -170,6 +175,7 @@ class LiveUser: ObservableObject { self.playlists = PlaylistApi.fromJSON(playlist: playlists).sorted(by: { $0.name.lowercased() < $1.name.lowercased() }) self.isRefreshingPlaylists = false + self.isInitiallyRefreshingPlaylists = false if let success = onSuccess { Logger.sys.debug("successfully refreshed playlists") @@ -219,6 +225,7 @@ class LiveUser: ObservableObject { self.tags = TagApi.fromJSON(tag: tags).sorted(by: { $0.name.lowercased() < $1.name.lowercased() }) self.isRefreshingTags = false + self.isInitiallyRefreshingTags = false if let success = onSuccess { Logger.sys.debug("successfully refreshed tags") diff --git a/Mixonomer/Views/AppSkeleton.swift b/Mixonomer/Views/AppSkeleton.swift index 8dc4548..d44be64 100644 --- a/Mixonomer/Views/AppSkeleton.swift +++ b/Mixonomer/Views/AppSkeleton.swift @@ -17,53 +17,62 @@ struct AppSkeleton: View { @State private var selection = 0 // Tab view selection var body: some View { - TabView { - - PlaylistList() - .tabItem { - VStack { - Image(systemName: "music.note.list") - Text("Playlists") - } + + if self.liveUser.isInitiallyRefreshingUser + || self.liveUser.isInitiallyRefreshingPlaylists + || self.liveUser.isInitiallyRefreshingTags + { + LoadingScreen() + .onAppear { + self.fetchAll() } - .tag(0) + } else { - if liveUser.lastfm_connected() { + TabView { - TagList() + PlaylistList() .tabItem { VStack { - Image(systemName: "tag") - Text("Tags") + Image(systemName: "music.note.list") + Text("Playlists") } } - .tag(1) - } - - if let user = liveUser.user { - if user.type == .admin { - AdminList() - .tabItem( { + .tag(0) + + if liveUser.lastfm_connected() { + + TagList() + .tabItem { VStack { - Image(systemName: "person.badge.key.fill") - Text("Admin") + Image(systemName: "tag") + Text("Tags") } - }) - .tag(2) + } + .tag(1) } - } - - SettingsList() - .tabItem { - VStack { - Image(systemName: "slider.horizontal.3") - Text("Settings") + + if let user = liveUser.user { + if user.type == .admin { + AdminList() + .tabItem( { + VStack { + Image(systemName: "person.badge.key.fill") + Text("Admin") + } + }) + .tag(2) } } - .tag(3) - - }.onAppear { - self.fetchAll() + + SettingsList() + .tabItem { + VStack { + Image(systemName: "slider.horizontal.3") + Text("Settings") + } + } + .tag(3) + } } } diff --git a/Mixonomer/Views/LoadingScreen.swift b/Mixonomer/Views/LoadingScreen.swift new file mode 100644 index 0000000..71e5b32 --- /dev/null +++ b/Mixonomer/Views/LoadingScreen.swift @@ -0,0 +1,38 @@ +// +// LoadingScreen.swift +// Mixonomer +// +// Created by Andy Pack on 10/12/2022. +// Copyright © 2022 Sarsoo. All rights reserved. +// + +import SwiftUI + +struct LoadingScreen: View { + + var frameSize: CGFloat = 144 + @State private var isAnimating = false + + var body: some View { + Image("Splash") + // framing + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: frameSize) + // animation + .rotationEffect(Angle(degrees: isAnimating ? 360.0 : 0.0)) + .animation( +// .easeInOut(duration: 1) + .spring(response: 0.7, dampingFraction: 0.8, blendDuration: 0) + .repeatForever(autoreverses: false), value: isAnimating) + .onAppear { + isAnimating = true + } + } +} + +struct LoadingScreen_Previews: PreviewProvider { + static var previews: some View { + LoadingScreen() + } +}