diff --git a/Balance.xcodeproj/project.pbxproj b/Balance.xcodeproj/project.pbxproj index dd54b99..1dd66d3 100644 --- a/Balance.xcodeproj/project.pbxproj +++ b/Balance.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ 6C39EA2229C9EA620095573E /* SOSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C39EA2029C9EA610095573E /* SOSView.swift */; }; 6C3BB1F32A151D1F008FEB93 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3BB1F22A151D1F008FEB93 /* SearchBar.swift */; }; 6C3BB1F52A1646C5008FEB93 /* PasswordResetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3BB1F42A1646C5008FEB93 /* PasswordResetView.swift */; }; + 6C3D39972A812D0F00864CC0 /* AccesoryArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3D39962A812D0F00864CC0 /* AccesoryArray.swift */; }; 6C3DD6E42A126DAF00456646 /* GuessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3DD6E32A126DAF00456646 /* GuessView.swift */; }; 6C3DD6E62A12742D00456646 /* BoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3DD6E52A12742D00456646 /* BoxView.swift */; }; 6C4676CB2A031C1200777421 /* NewTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4676CA2A031C1200777421 /* NewTimerView.swift */; }; @@ -102,6 +103,8 @@ 6C58B25029F6B673000FE8DD /* DrawHighlightView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C58B24F29F6B673000FE8DD /* DrawHighlightView.swift */; }; 6C58B25229F7293A000FE8DD /* NavigationUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C58B25129F7293A000FE8DD /* NavigationUtil.swift */; }; 6C60EFA12A16548F00A01862 /* ShakeGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C60EFA02A16548F00A01862 /* ShakeGesture.swift */; }; + 6C738BDD2A82795F009B359E /* PresentBannerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C738BDC2A82795F009B359E /* PresentBannerManager.swift */; }; + 6C738BDF2A827B67009B359E /* GlobalBannerContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C738BDE2A827B67009B359E /* GlobalBannerContent.swift */; }; 6C80C01829CCF90B003DD5B9 /* Nunito-SemiBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6C80C00829CCF8FA003DD5B9 /* Nunito-SemiBoldItalic.ttf */; }; 6C80C01929CCF90B003DD5B9 /* Nunito-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6C80C00929CCF8FB003DD5B9 /* Nunito-BlackItalic.ttf */; }; 6C80C01A29CCF90B003DD5B9 /* Nunito-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6C80C00A29CCF8FD003DD5B9 /* Nunito-MediumItalic.ttf */; }; @@ -245,6 +248,7 @@ 6C39EA2029C9EA610095573E /* SOSView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SOSView.swift; sourceTree = ""; }; 6C3BB1F22A151D1F008FEB93 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = ""; }; 6C3BB1F42A1646C5008FEB93 /* PasswordResetView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordResetView.swift; sourceTree = ""; }; + 6C3D39962A812D0F00864CC0 /* AccesoryArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccesoryArray.swift; sourceTree = ""; }; 6C3DD6E32A126DAF00456646 /* GuessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessView.swift; sourceTree = ""; }; 6C3DD6E52A12742D00456646 /* BoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = ""; }; 6C4676CA2A031C1200777421 /* NewTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTimerView.swift; sourceTree = ""; }; @@ -282,6 +286,8 @@ 6C58B24F29F6B673000FE8DD /* DrawHighlightView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawHighlightView.swift; sourceTree = ""; }; 6C58B25129F7293A000FE8DD /* NavigationUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationUtil.swift; sourceTree = ""; }; 6C60EFA02A16548F00A01862 /* ShakeGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShakeGesture.swift; sourceTree = ""; }; + 6C738BDC2A82795F009B359E /* PresentBannerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentBannerManager.swift; sourceTree = ""; }; + 6C738BDE2A827B67009B359E /* GlobalBannerContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalBannerContent.swift; sourceTree = ""; }; 6C80C00829CCF8FA003DD5B9 /* Nunito-SemiBoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-SemiBoldItalic.ttf"; sourceTree = ""; }; 6C80C00929CCF8FB003DD5B9 /* Nunito-BlackItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-BlackItalic.ttf"; sourceTree = ""; }; 6C80C00A29CCF8FD003DD5B9 /* Nunito-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-MediumItalic.ttf"; sourceTree = ""; }; @@ -574,6 +580,7 @@ 6CA4EFE529EDEBB000877850 /* AccesoryView.swift */, 6C0A4BF129E9B10F003007C7 /* Avatar.swift */, 6C0A4BF429E9BCC1003007C7 /* Accesory.swift */, + 6C3D39962A812D0F00864CC0 /* AccesoryArray.swift */, 6CAA076429E9FB3D00541F87 /* AvatarPreviewView.swift */, 6C5523F229F8013B00F802D9 /* ProfileView.swift */, 6C5523F429F8094C00F802D9 /* PasswordUpdateView.swift */, @@ -706,6 +713,8 @@ 6C3BB1F22A151D1F008FEB93 /* SearchBar.swift */, 6C60EFA02A16548F00A01862 /* ShakeGesture.swift */, 6C92E3C12A17C84E003FE239 /* RoundedCorner.swift */, + 6C738BDC2A82795F009B359E /* PresentBannerManager.swift */, + 6C738BDE2A827B67009B359E /* GlobalBannerContent.swift */, ); path = Utils; sourceTree = ""; @@ -1095,6 +1104,7 @@ 6C47338B29FAB89900DC72D0 /* SignUpView.swift in Sources */, 2F4E23832989D51F0013F3D9 /* BalanceAppTestingSetup.swift in Sources */, 2720084329A843B90052908D /* Note.swift in Sources */, + 6C738BDD2A82795F009B359E /* PresentBannerManager.swift in Sources */, 6CFB02492A4486C2000045E1 /* VideoArray.swift in Sources */, 6C55243A29F8722B00F802D9 /* AuthViewModel.swift in Sources */, 6CB5181E29E6F395007AADB4 /* ImageView.swift in Sources */, @@ -1122,6 +1132,7 @@ 2720083D29A7E5830052908D /* PastDiaryEntry.swift in Sources */, 5EF9D78429B5AFF1006C3B22 /* ActivityStorageManager.swift in Sources */, 6CFDD58A2A0D9ECE009D7E56 /* ColoringHomeView.swift in Sources */, + 6C3D39972A812D0F00864CC0 /* AccesoryArray.swift in Sources */, 6CF978992A65EC970046E90A /* EmailHelper.swift in Sources */, 6C0A4BEE29E9B053003007C7 /* AvatarSelectionView.swift in Sources */, 6CF510C029C8FD25008A2F55 /* LocationView.swift in Sources */, @@ -1139,6 +1150,7 @@ 894A884529B7B27600CB347B /* NavigationView.swift in Sources */, 6C5523F529F8094C00F802D9 /* PasswordUpdateView.swift in Sources */, 2761584B29A6548B006C7AC1 /* SpotifyView.swift in Sources */, + 6C738BDF2A827B67009B359E /* GlobalBannerContent.swift in Sources */, 6CB5181C29E45C0C007AADB4 /* BalanceExtensions.swift in Sources */, 6C55242629F86D9200F802D9 /* BalanceAccount.swift in Sources */, 6C9980732A45EADD00351F7C /* PhotoUploadView.swift in Sources */, diff --git a/Balance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Balance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6f4aced..a18a415 100644 --- a/Balance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Balance.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/firebase/firebase-ios-sdk.git", "state" : { - "revision" : "e700a8f40c87c31cab7984875fcc1225d96b25bf", - "version" : "10.11.0" + "revision" : "5034479ca0c4f32f299677fb0ba1fe4d3e3e20b4", + "version" : "10.10.0" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/GoogleAppMeasurement.git", "state" : { - "revision" : "62e3a0c09a75e2637f5300d46f05a59313f1c286", - "version" : "10.11.0" + "revision" : "69f5b8425dd473d2f2475bba7f88f82cd9da0e36", + "version" : "10.10.0" } }, { diff --git a/Balance/ActivityLogging/ActivityLogBaseView.swift b/Balance/ActivityLogging/ActivityLogBaseView.swift index 36841d8..31f2fae 100644 --- a/Balance/ActivityLogging/ActivityLogBaseView.swift +++ b/Balance/ActivityLogging/ActivityLogBaseView.swift @@ -9,7 +9,7 @@ import SwiftUI // swiftlint:disable lower_acl_than_parent struct ActivityLogContainer: View where Content: View { - @StateObject var activityLogEntry = ActivityLogEntry() + @EnvironmentObject var activityLogEntry: ActivityLogEntry private let content: Content var body: some View { @@ -31,6 +31,9 @@ struct ActivityLogBaseView: View where Content: View { var body: some View { content + .onReceive(NotificationCenter.default.publisher(for: Notification.Name.goBackground)) { _ in + activityLogEntry.reset() + } .onAppear(perform: { activityLogEntry.addAction(actionDescription: "Opened \(viewName)") #if DEBUG @@ -43,11 +46,6 @@ struct ActivityLogBaseView: View where Content: View { if isDirectChildToContainer { #if DEMO logStore.saveLog(activityLogEntry) - ActivityLogStore.save(logs: logStore.logs) { result in - if case .failure(let error) = result { - print(error.localizedDescription) - } - } #else ActivityStorageManager.shared.uploadActivity(activityLogEntry: activityLogEntry) #endif diff --git a/Balance/ActivityLogging/ActivityLogStore.swift b/Balance/ActivityLogging/ActivityLogStore.swift index 6a8935a..5b39b96 100644 --- a/Balance/ActivityLogging/ActivityLogStore.swift +++ b/Balance/ActivityLogging/ActivityLogStore.swift @@ -11,7 +11,7 @@ import SwiftUI class ActivityLogStore: ObservableObject { static let shared = ActivityLogStore() @Published var logs: [ActivityLogEntry] = [] - + private static func fileURL() throws -> URL { try FileManager.default.url( for: .documentDirectory, @@ -19,7 +19,7 @@ class ActivityLogStore: ObservableObject { appropriateFor: nil, create: false ) - .appendingPathComponent("activityLog.data") + .appendingPathComponent("\(UserDefaults.standard.string(forKey: "lastPatient") ?? "")_activityLog.data") } static func load(completion: @escaping (Result<[ActivityLogEntry], Error>) -> Void) { @@ -85,14 +85,22 @@ class ActivityLogStore: ObservableObject { } func saveLog(_ log: ActivityLogEntry) { - let indexOfLog = logs.firstIndex { currentLog in - currentLog.id == log.id - } - - if let indexOfLog { - logs[indexOfLog] = log - } else { - logs.append(log) + ActivityLogStore.load { result in + switch result { + case .failure(let error): + print(error.localizedDescription) + case .success(let logs): + self.logs = logs.filter({ + $0.id != log.id + }) + self.logs.append(log) + + ActivityLogStore.save(logs: self.logs) { result in + if case .failure(let error) = result { + print(error.localizedDescription) + } + } + } } } } diff --git a/Balance/ActivityLogging/ActivityStorageManager.swift b/Balance/ActivityLogging/ActivityStorageManager.swift index 6a1eab1..669df0e 100644 --- a/Balance/ActivityLogging/ActivityStorageManager.swift +++ b/Balance/ActivityLogging/ActivityStorageManager.swift @@ -20,23 +20,25 @@ import Foundation total duration: */ -// swiftlint:disable implicit_return -// swiftlint:disable force_unwrapping -// swiftlint:disable todo -// swiftlint:disable untyped_error_in_catch +// swiftlint:disable all struct LogAction { - let id: String + let sessionID: String + let sessionStartTime: Date + let sessionEndTime: Date + let sessionDuration: Int + let description: String let startTime: Date let endTime: Date - let duration: TimeInterval - let actionTime: Date - let actionDesc: String + let duration: Int } struct Action: Codable { - let time: Date + var id = UUID().uuidString let description: String + let startTime: Date + var endTime = Date.now + var duration: Int = 0 } class ActivityLogEntry: ObservableObject, Codable { @@ -47,49 +49,92 @@ class ActivityLogEntry: ObservableObject, Codable { case duration case actions } - + var id = UUID().uuidString - var startTime = Date(timeIntervalSinceReferenceDate: 0) - var endTime = Date(timeIntervalSinceReferenceDate: 0) - var duration: TimeInterval = 0 + var startTime = Date() + var endTime = Date.now + var duration: Int = 0 var actions: [Action] = [] func reset() { id = UUID().uuidString - startTime = Date(timeIntervalSinceReferenceDate: 0) + startTime = Date() endTime = startTime duration = 0 actions = [] } func isEmpty() -> Bool { - return getDuration() == TimeInterval(0) + return getDuration() == 0 } func addAction(actionDescription: String) { let currentDate = Date.now - actions.append(Action(time: currentDate, description: actionDescription)) - - // set start time if this is the first action - startTime = startTime == Date(timeIntervalSinceReferenceDate: 0) ? currentDate : startTime + actions.append(Action(description: actionDescription, startTime: currentDate)) } func addActionButton(actionDescription: String) { let currentDate = Date.now - actions.append(Action(time: currentDate, description: actionDescription)) - + actions.append( + Action( + description: actionDescription, + startTime: currentDate, + endTime: currentDate, + duration: 0 + ) + ) // set start time if this is the first action - startTime = startTime == Date(timeIntervalSinceReferenceDate: 0) ? currentDate : startTime - endTime = startTime - duration = getDuration() + startTime = currentDate + endTime = currentDate + + duration = 0 } func endLog(actionDescription: String) { - addAction(actionDescription: actionDescription) - endTime = actions.last!.time - duration = getDuration() + let currentEndDate = Date.now + let startAction = actions.last(where: { + $0.description == actionDescription.replacingOccurrences(of: "Closed", with: "Opened") + }) + + if startAction == nil { + return + } + let interval = currentEndDate - startAction!.startTime + actions.append( + Action( + description: actionDescription.replacingOccurrences(of: "Closed ", with: ""), + startTime: startAction!.startTime, + endTime: currentEndDate, + duration: interval.second ?? 0 + ) + ) + actions = actions.filter( { + $0.id != startAction?.id + }) + + if actionDescription.contains("Closed Image Highlight") || + actionDescription.contains("Closed Image Selected") || + actionDescription.contains("Closed Video Highlight") || + actionDescription.contains("Closed Video Selected") || + actionDescription.contains("Closed Sudoku Game") || + actionDescription.contains("Closed Crossover Game") || + actionDescription.contains("Closed Guess the Emotion") || + actionDescription.contains("Closed How is your mood") || + actionDescription.contains("Closed Draw Something") || + actionDescription.contains("Closed Coloring Something") || + actionDescription.contains("Closed Playing Spotify") { + if (interval.second ?? 0) > coinsTime { + NotificationCenter.default.post(name: Notification.Name.coinsUpdate, object: nil) + } + } + + print(interval.second ?? 0) + startTime = actions.first!.startTime + endTime = actions.last!.endTime + let intervalSession = endTime - startTime + duration = intervalSession.second ?? 0 } - + func getDuration() -> TimeInterval { return endTime.timeIntervalSinceReferenceDate - startTime.timeIntervalSinceReferenceDate } @@ -104,7 +149,7 @@ class ActivityLogEntry: ObservableObject, Codable { var actionsStr = "" for action in actions { - actionsStr.append("\(dateToString(date: action.time) + " " + action.description)\n") + actionsStr.append("\(dateToString(date: action.startTime) + " " + action.description)\n") } return (idStr, [startStr, actionsStr, durationStr, endStr].joined(separator: "\n")) diff --git a/Balance/Balance.swift b/Balance/Balance.swift index 591034d..201d603 100644 --- a/Balance/Balance.swift +++ b/Balance/Balance.swift @@ -9,6 +9,7 @@ import CardinalKit import SwiftUI +// swiftlint:disable closure_body_length @main struct Balance: App { @UIApplicationDelegateAdaptor(BalanceAppDelegate.self) @@ -22,7 +23,11 @@ struct Balance: App { #if DEMO @StateObject var logStore = ActivityLogStore() #endif - @State var started = false + @StateObject var activityLogEntry = ActivityLogEntry() + @StateObject var bannerManager = PresentBannerManager() + + @Environment(\.scenePhase) + var scenePhase var body: some Scene { WindowGroup { @@ -32,6 +37,9 @@ struct Balance: App { } else { OnboardingFlow() } + if bannerManager.isPresented { + GlobalBannerContent(bannerManager: bannerManager) + } } .testingSetup() .cardinalKit(appDelegate) @@ -42,6 +50,25 @@ struct Balance: App { #if DEMO .environmentObject(logStore) #endif + .environmentObject(activityLogEntry) + .environmentObject(bannerManager) + .onChange(of: scenePhase) { phase in + switch phase { + case .active: + print("ScenePhase: active") + UserDefaults.standard.set(false, forKey: StorageKeys.spotifyConnect) + case .background: + print("ScenePhase: background") + let value = UserDefaults.standard.bool(forKey: StorageKeys.spotifyConnect) + if value == false { + activityLogEntry.reset() + } + case .inactive: + print("ScenePhase: inactive") + @unknown default: + print("ScenePhase: unexpected state") + } + } } } } diff --git a/Balance/Chill/BodySensationView.swift b/Balance/Chill/BodySensationView.swift index 394d9bd..e12599d 100644 --- a/Balance/Chill/BodySensationView.swift +++ b/Balance/Chill/BodySensationView.swift @@ -9,21 +9,19 @@ import SwiftUI struct BodySensationView: View { var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Body sensations") - Spacer() - titleText - Spacer() - imageView - Spacer() - subTitleText - bodyButtons - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Body sensations") + Spacer() + titleText + Spacer() + imageView Spacer() + subTitleText + bodyButtons } + Spacer() } } @@ -189,13 +187,13 @@ struct BodySensationView: View { ) } } - + var imageView: some View { - Image("bodyAvatar") - .resizable() - .scaledToFit() - .frame(width: 250, height: 250, alignment: .center) - .accessibilityLabel("imageBS") + Image("bodyAvatar") + .resizable() + .scaledToFit() + .frame(width: 250, height: 250, alignment: .center) + .accessibilityLabel("imageBS") } var titleText: some View { diff --git a/Balance/Chill/ChillView.swift b/Balance/Chill/ChillView.swift index e7ef7f4..854b617 100644 --- a/Balance/Chill/ChillView.swift +++ b/Balance/Chill/ChillView.swift @@ -9,21 +9,19 @@ import SwiftUI struct ChillView: View { var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Let's chill out") - whatTitle - ScrollView(.vertical) { - VStack(spacing: 20) { - bodySensationOption - breathingOption - guidedMeditationOption - } - .padding(10) - .ignoresSafeArea(.all) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Let's chill out") + whatTitle + ScrollView(.vertical) { + VStack(spacing: 20) { + bodySensationOption + breathingOption + guidedMeditationOption } + .padding(10) + .ignoresSafeArea(.all) } } } diff --git a/Balance/Chill/Meditation/MeditationSpotifyView.swift b/Balance/Chill/Meditation/MeditationSpotifyView.swift index 67d75f5..1798ef9 100644 --- a/Balance/Chill/Meditation/MeditationSpotifyView.swift +++ b/Balance/Chill/Meditation/MeditationSpotifyView.swift @@ -17,9 +17,9 @@ struct Song: Identifiable { let spotifyURL: String } -// swiftlint:disable attributes struct MeditationSpotifyView: View { - @Environment(\.openURL) private var openURL + @Environment(\.openURL) + private var openURL let songs = [ Song( diff --git a/Balance/Chill/Meditation/MeditationView.swift b/Balance/Chill/Meditation/MeditationView.swift index fa84c92..d8fd83a 100644 --- a/Balance/Chill/Meditation/MeditationView.swift +++ b/Balance/Chill/Meditation/MeditationView.swift @@ -21,27 +21,25 @@ struct MeditationView: View { ] var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Guided Meditation") - VStack(alignment: .center, spacing: 10) { - highlightsTitle.padding(.horizontal, 10.0) - videoPaging - categoriesTitle.padding(.horizontal, 10.0) - tagsView.padding(.horizontal, 10.0) - if showingGuided { - MeditationSpotifyView().padding(.horizontal, 10.0) - } else if showingYoutube { - YoutubeView().padding(.horizontal, 10.0) - } else if showingSleep { - SleepView().padding(.horizontal, 10.0) - } - Spacer() + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Guided Meditation") + VStack(alignment: .center, spacing: 10) { + highlightsTitle.padding(.horizontal, 10.0) + videoPaging + categoriesTitle.padding(.horizontal, 10.0) + tagsView.padding(.horizontal, 10.0) + if showingGuided { + MeditationSpotifyView().padding(.horizontal, 10.0) + } else if showingYoutube { + YoutubeView().padding(.horizontal, 10.0) + } else if showingSleep { + SleepView().padding(.horizontal, 10.0) } - .edgesIgnoringSafeArea(.all) + Spacer() } + .edgesIgnoringSafeArea(.all) } } } diff --git a/Balance/Chill/Meditation/SleepView.swift b/Balance/Chill/Meditation/SleepView.swift index 87446e9..9db0d13 100644 --- a/Balance/Chill/Meditation/SleepView.swift +++ b/Balance/Chill/Meditation/SleepView.swift @@ -8,9 +8,9 @@ import SwiftUI -// swiftlint:disable attributes struct SleepView: View { - @Environment(\.openURL) var openURL + @Environment(\.openURL) + var openURL let songs = [ Song( diff --git a/Balance/Chill/Timer/NewTimerView.swift b/Balance/Chill/Timer/NewTimerView.swift index dc42a94..68015fc 100644 --- a/Balance/Chill/Timer/NewTimerView.swift +++ b/Balance/Chill/Timer/NewTimerView.swift @@ -48,36 +48,34 @@ struct NewTimerView: View { @State var scale: CGFloat = 1.0 @State var breathStp: Int = 0 var countTo: Int = 120 // 4 minutes 120 - 2minutes - + var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack(alignment: .center) { - HeaderMenu(title: navTitleText) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack(alignment: .center) { + HeaderMenu(title: navTitleText) + Spacer() + subTitle + Spacer() + Clock(counter: counter, countTo: countTo) + Spacer() + progressAnimation + Group { Spacer() - subTitle + actionButton Spacer() - Clock(counter: counter, countTo: countTo) + sliderView Spacer() - progressAnimation - Group { - Spacer() - actionButton - Spacer() - sliderView - Spacer() - } - } - .onReceive(timer) { _ in - receiveAction() - } - .onAppear { - timerAnimation = Timer - .publish(every: (self.chillType == .breathing) ? 5.0 : 2.0, on: .main, in: .common) - .autoconnect() } } + .onReceive(timer) { _ in + receiveAction() + } + .onAppear { + timerAnimation = Timer + .publish(every: (self.chillType == .breathing) ? 5.0 : 2.0, on: .main, in: .common) + .autoconnect() + } } } @@ -451,7 +449,7 @@ struct NewTimerView: View { } } } - + func completed() -> Bool { let value = progress() == 1 return value diff --git a/Balance/Diary/Store/NoteStore.swift b/Balance/Diary/Store/NoteStore.swift index ecd500f..64b3e86 100644 --- a/Balance/Diary/Store/NoteStore.swift +++ b/Balance/Diary/Store/NoteStore.swift @@ -11,7 +11,7 @@ import SwiftUI class NoteStore: ObservableObject { static let shared = NoteStore() @Published var notes: [Note] = [] - + private static func fileURL() throws -> URL { try FileManager.default.url( for: .documentDirectory, @@ -19,7 +19,7 @@ class NoteStore: ObservableObject { appropriateFor: nil, create: false ) - .appendingPathComponent("diary.data") + .appendingPathComponent("\(UserDefaults.standard.string(forKey: "lastPatient") ?? "")_diary.data") } static func load(completion: @escaping (Result<[Note], Error>) -> Void) { diff --git a/Balance/Diary/Views/DiaryHomeView.swift b/Balance/Diary/Views/DiaryHomeView.swift index f94a4e9..df3c9cc 100644 --- a/Balance/Diary/Views/DiaryHomeView.swift +++ b/Balance/Diary/Views/DiaryHomeView.swift @@ -8,9 +8,9 @@ import SwiftUI -// swiftlint:disable attributes struct DiaryHomeView: View { - @Environment(\.scenePhase) private var scenePhase + @Environment(\.scenePhase) + private var scenePhase @EnvironmentObject var store: NoteStore @State private var showingEditor = false @State private var searchText = "" @@ -22,35 +22,33 @@ struct DiaryHomeView: View { ) var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Diary") - VStack(alignment: .center, spacing: 10) { - newDiaryView - previusView - diaryList - } - .sheet(isPresented: $showingEditor) { - ActivityLogBaseView(viewName: "Diary Note Entry View") { - diaryNoteView - } - } - .onAppear { - loadNote() + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Diary") + VStack(alignment: .center, spacing: 10) { + newDiaryView + previusView + diaryList + } + .sheet(isPresented: $showingEditor) { + ActivityLogBaseView(viewName: "Diary Note Entry View") { + diaryNoteView } - .onChange(of: scenePhase) { phase in - if phase == .inactive { - NoteStore.save(notes: store.notes) { result in - if case .failure(let error) = result { - print(error.localizedDescription) - } + } + .onAppear { + loadNote() + } + .onChange(of: scenePhase) { phase in + if phase == .inactive { + NoteStore.save(notes: store.notes) { result in + if case .failure(let error) = result { + print(error.localizedDescription) } } } - .edgesIgnoringSafeArea(.all) } + .edgesIgnoringSafeArea(.all) } } } diff --git a/Balance/Diary/Views/DiaryNoteEntryView.swift b/Balance/Diary/Views/DiaryNoteEntryView.swift index 79bb12a..8bb08a5 100644 --- a/Balance/Diary/Views/DiaryNoteEntryView.swift +++ b/Balance/Diary/Views/DiaryNoteEntryView.swift @@ -21,34 +21,32 @@ struct DiaryNoteEntryView: View { @State private var burningNote = false @State private var burnComplete = false @State private var emptyNoteAlert = false - + var body: some View { - ActivityLogContainer { - ZStack { - VStack { - TextField("Note Title", text: $title) - .font(.custom("Nunito-Bold", size: 18)) - .padding() - TextEditor(text: $text) - .font(.custom("Nunito", size: 16)) - .border(.black.opacity(0.2), width: 1) - .padding() - saveView - .frame(maxWidth: .infinity, alignment: .center) - .padding() - notesList - }.onAppear { - self.title = currentNote.title - self.text = currentNote.text - self.id = currentNote.id - } - - if burningNote { - BurnedView( - burningNote: $burningNote, - showingEditor: $showingEditor - ) - } + ZStack { + VStack { + TextField("Note Title", text: $title) + .font(.custom("Nunito-Bold", size: 18)) + .padding() + TextEditor(text: $text) + .font(.custom("Nunito", size: 16)) + .border(.black.opacity(0.2), width: 1) + .padding() + saveView + .frame(maxWidth: .infinity, alignment: .center) + .padding() + notesList + }.onAppear { + self.title = currentNote.title + self.text = currentNote.text + self.id = currentNote.id + } + + if burningNote { + BurnedView( + burningNote: $burningNote, + showingEditor: $showingEditor + ) } } } diff --git a/Balance/Diary/Views/PastDiaryEntry.swift b/Balance/Diary/Views/PastDiaryEntry.swift index 1e9fda9..4dfde48 100644 --- a/Balance/Diary/Views/PastDiaryEntry.swift +++ b/Balance/Diary/Views/PastDiaryEntry.swift @@ -12,32 +12,30 @@ public struct PastDiaryEntry: View { private var note: Note public var body: some View { - ActivityLogContainer { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(note.date.timeSinceDate(fromDate: Date())) - .font(.custom("Nunito-Bold", size: 11)) - .foregroundColor(.gray) - Text(note.title) - .font(.custom("Nunito-Black", size: 18)) - .foregroundColor(darkBlueColor) - Text(note.text) - .font(.custom("Nunito", size: 14)) - .foregroundColor(.gray) - .lineLimit(3) - .frame(maxWidth: 270, alignment: .leading) - } - Image(systemName: "chevron.right") + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(note.date.timeSinceDate(fromDate: Date())) + .font(.custom("Nunito-Bold", size: 11)) + .foregroundColor(.gray) + Text(note.title) + .font(.custom("Nunito-Black", size: 18)) .foregroundColor(darkBlueColor) + Text(note.text) + .font(.custom("Nunito", size: 14)) + .foregroundColor(.gray) + .lineLimit(3) + .frame(maxWidth: 270, alignment: .leading) } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(20) - .background(.white) - .cornerRadius(15) - .shadow(color: Color.black.opacity(0.1), radius: 5) + Image(systemName: "chevron.right") + .foregroundColor(darkBlueColor) } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(20) + .background(.white) + .cornerRadius(15) + .shadow(color: Color.black.opacity(0.1), radius: 5) } - + public init(_ note: Note) { self.note = note } diff --git a/Balance/Distraction/DistractionCellView.swift b/Balance/Distraction/DistractionCellView.swift index 2ca5b8f..9a6fb2d 100644 --- a/Balance/Distraction/DistractionCellView.swift +++ b/Balance/Distraction/DistractionCellView.swift @@ -13,27 +13,25 @@ struct DistractionCellView: View { var pointVal: String var body: some View { - ActivityLogContainer { - HStack { - iconView - VStack { - HStack { - Spacer() - pointValueView - } - Spacer() - textView + HStack { + iconView + VStack { + HStack { Spacer() + pointValueView } + Spacer() + textView + Spacer() } - .frame(maxWidth: 311, maxHeight: 120) - .foregroundColor(darkBlueColor) - .background(RoundedRectangle(cornerRadius: 20).fill(.white)) - .clipped() - .frame(height: 120.0) - .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) - .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } + .frame(maxWidth: 311, maxHeight: 120) + .foregroundColor(darkBlueColor) + .background(RoundedRectangle(cornerRadius: 20).fill(.white)) + .clipped() + .frame(height: 120.0) + .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } var textView: some View { diff --git a/Balance/Distraction/DistractionView.swift b/Balance/Distraction/DistractionView.swift index 83b078f..72321ee 100644 --- a/Balance/Distraction/DistractionView.swift +++ b/Balance/Distraction/DistractionView.swift @@ -10,25 +10,23 @@ import SwiftUI struct DistractionView: View { @State private var currentDraw = Draw() @EnvironmentObject var store: DrawStore - + var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack(spacing: 0) { - HeaderMenu(title: "Distraction") - ScrollView(.vertical) { - VStack(spacing: 20) { - picturesOption - musicOption - videosOption - gamesOption - drawingOption - coloringOption - } - .padding(20) - .ignoresSafeArea(.all) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack(spacing: 0) { + HeaderMenu(title: "Distraction") + ScrollView(.vertical) { + VStack(spacing: 20) { + picturesOption + musicOption + videosOption + gamesOption + drawingOption + coloringOption } + .padding(20) + .ignoresSafeArea(.all) } } } @@ -44,7 +42,7 @@ struct DistractionView: View { } ) ) { - CellView(image: "drawingIcon", text: "Coloring something") + DistractionCellView(image: "drawingIcon", text: "Coloring something", pointVal: "5") } } @@ -58,7 +56,7 @@ struct DistractionView: View { } ) ) { - CellView(image: "writesIcon", text: "Drawing something") + DistractionCellView(image: "writesIcon", text: "Drawing something", pointVal: "5") } } @@ -72,7 +70,7 @@ struct DistractionView: View { } ) ) { - CellView(image: "sudokuIcon", text: "Games") + DistractionCellView(image: "sudokuIcon", text: "Games", pointVal: "5") } } @@ -86,7 +84,7 @@ struct DistractionView: View { } ) ) { - CellView(image: "videosIcon", text: "Look at videos") + DistractionCellView(image: "videosIcon", text: "Look at videos", pointVal: "5") } } @@ -100,7 +98,7 @@ struct DistractionView: View { } ) ) { - CellView(image: "musicIcon", text: "Listen to music") + DistractionCellView(image: "musicIcon", text: "Listen to music", pointVal: "5") } } @@ -114,7 +112,7 @@ struct DistractionView: View { } ) ) { - CellView(image: "picturesIcon", text: "Look at pictures") + DistractionCellView(image: "picturesIcon", text: "Look at pictures", pointVal: "5") } } } diff --git a/Balance/Distraction/Drawing/BackgroundDrawView.swift b/Balance/Distraction/Drawing/BackgroundDrawView.swift index 6ca6f75..352c571 100644 --- a/Balance/Distraction/Drawing/BackgroundDrawView.swift +++ b/Balance/Distraction/Drawing/BackgroundDrawView.swift @@ -45,20 +45,18 @@ struct BackgroundDrawView: View { let highlightArray = mandalaArray.filter { $0.highlight == true } var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Coloring Something") - VStack(alignment: .center, spacing: 10) { - highlightsTitle - imagePaging - categoriesTitle - tagsView - Spacer() - } - .edgesIgnoringSafeArea(.all) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Coloring Something") + VStack(alignment: .center, spacing: 10) { + highlightsTitle + imagePaging + categoriesTitle + tagsView + Spacer() } + .edgesIgnoringSafeArea(.all) } } } diff --git a/Balance/Distraction/Drawing/ColoringHomeView.swift b/Balance/Distraction/Drawing/ColoringHomeView.swift index 58440e2..3e4ba9d 100644 --- a/Balance/Distraction/Drawing/ColoringHomeView.swift +++ b/Balance/Distraction/Drawing/ColoringHomeView.swift @@ -7,45 +7,43 @@ import SwiftUI -// swiftlint:disable attributes struct ColoringHomeView: View { @EnvironmentObject var store: ColoringStore @State private var currentDraw = Draw() - @Environment(\.scenePhase) private var scenePhase + @Environment(\.scenePhase) + private var scenePhase @State private var isShowingSecondView = false var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Coloring Something") - VStack(alignment: .center, spacing: 10) { - newDrawView - previusView - drawList - } - .onAppear { - ColoringStore.load { result in - switch result { - case .failure(let error): - print(error.localizedDescription) - case .success(let draws): - store.coloringDraws = draws - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Coloring Something") + VStack(alignment: .center, spacing: 10) { + newDrawView + previusView + drawList + } + .onAppear { + ColoringStore.load { result in + switch result { + case .failure(let error): + print(error.localizedDescription) + case .success(let draws): + store.coloringDraws = draws } } - .onChange(of: scenePhase) { phase in - if phase == .inactive { - ColoringStore.save(coloringDraws: store.coloringDraws) { result in - if case .failure(let error) = result { - print(error.localizedDescription) - } + } + .onChange(of: scenePhase) { phase in + if phase == .inactive { + ColoringStore.save(coloringDraws: store.coloringDraws) { result in + if case .failure(let error) = result { + print(error.localizedDescription) } } } - .edgesIgnoringSafeArea(.all) } + .edgesIgnoringSafeArea(.all) } } } diff --git a/Balance/Distraction/Drawing/ColoringStore.swift b/Balance/Distraction/Drawing/ColoringStore.swift index 93d9cf9..73d20b1 100644 --- a/Balance/Distraction/Drawing/ColoringStore.swift +++ b/Balance/Distraction/Drawing/ColoringStore.swift @@ -10,7 +10,7 @@ import SwiftUI class ColoringStore: ObservableObject { static let shared = ColoringStore() @Published var coloringDraws: [Draw] = [] - + private static func fileURL() throws -> URL { try FileManager.default.url( for: .documentDirectory, @@ -18,7 +18,7 @@ class ColoringStore: ObservableObject { appropriateFor: nil, create: false ) - .appendingPathComponent("coloring.data") + .appendingPathComponent("\(UserDefaults.standard.string(forKey: "lastPatient") ?? "")_coloring.data") } static func load(completion: @escaping (Result<[Draw], Error>) -> Void) { diff --git a/Balance/Distraction/Drawing/DrawHomeView.swift b/Balance/Distraction/Drawing/DrawHomeView.swift index 3f6200a..8ca4879 100644 --- a/Balance/Distraction/Drawing/DrawHomeView.swift +++ b/Balance/Distraction/Drawing/DrawHomeView.swift @@ -7,45 +7,43 @@ import SwiftUI -// swiftlint:disable attributes struct DrawHomeView: View { @EnvironmentObject var store: DrawStore @State private var currentDraw = Draw() - @Environment(\.scenePhase) private var scenePhase + @Environment(\.scenePhase) + private var scenePhase @State private var isShowingSecondView = false var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Drawing Something") - VStack(alignment: .center, spacing: 10) { - newDrawView - previusView - drawList - } - .onAppear { - DrawStore.load { result in - switch result { - case .failure(let error): - print(error.localizedDescription) - case .success(let draws): - store.draws = draws - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Drawing Something") + VStack(alignment: .center, spacing: 10) { + newDrawView + previusView + drawList + } + .onAppear { + DrawStore.load { result in + switch result { + case .failure(let error): + print(error.localizedDescription) + case .success(let draws): + store.draws = draws } } - .onChange(of: scenePhase) { phase in - if phase == .inactive { - DrawStore.save(draws: store.draws) { result in - if case .failure(let error) = result { - print(error.localizedDescription) - } + } + .onChange(of: scenePhase) { phase in + if phase == .inactive { + DrawStore.save(draws: store.draws) { result in + if case .failure(let error) = result { + print(error.localizedDescription) } } } - .edgesIgnoringSafeArea(.all) } + .edgesIgnoringSafeArea(.all) } } } diff --git a/Balance/Distraction/Drawing/DrawStore.swift b/Balance/Distraction/Drawing/DrawStore.swift index 9257e09..8f6ceb8 100644 --- a/Balance/Distraction/Drawing/DrawStore.swift +++ b/Balance/Distraction/Drawing/DrawStore.swift @@ -10,7 +10,7 @@ import SwiftUI class DrawStore: ObservableObject { static let shared = DrawStore() @Published var draws: [Draw] = [] - + private static func fileURL() throws -> URL { try FileManager.default.url( for: .documentDirectory, @@ -18,7 +18,7 @@ class DrawStore: ObservableObject { appropriateFor: nil, create: false ) - .appendingPathComponent("draw.data") + .appendingPathComponent("\(UserDefaults.standard.string(forKey: "lastPatient") ?? "")_draw.data") } static func load(completion: @escaping (Result<[Draw], Error>) -> Void) { diff --git a/Balance/Distraction/Drawing/DrawView.swift b/Balance/Distraction/Drawing/DrawView.swift index 9bcb374..a4763ca 100644 --- a/Balance/Distraction/Drawing/DrawView.swift +++ b/Balance/Distraction/Drawing/DrawView.swift @@ -9,10 +9,10 @@ import Foundation import PencilKit import SwiftUI -// swiftlint:disable attributes // swiftlint:disable type_body_length struct DrawingView: UIViewRepresentable { - @Environment(\.undoManager) private var undoManager + @Environment(\.undoManager) + private var undoManager @Binding var canvas: PKCanvasView @Binding var isdraw: Bool @Binding var type: PKInkingTool.InkType @@ -38,10 +38,11 @@ struct DrawingView: UIViewRepresentable { } } -// swiftlint:disable attributes struct DrawView: View { - @Environment(\.dismiss) var dismiss - @Environment(\.undoManager) private var undoManager + @Environment(\.dismiss) + var dismiss + @Environment(\.undoManager) + private var undoManager @EnvironmentObject var drawStore: DrawStore @EnvironmentObject var coloringStore: ColoringStore @Binding var currentDraw: Draw @@ -65,32 +66,30 @@ struct DrawView: View { @State var showLineWith = false var body: some View { - ActivityLogContainer { - ZStack { - Color.white.edgesIgnoringSafeArea(.all) - VStack(spacing: 10) { - if isColoring == true { - HeaderMenu(title: "Coloring Something") - } else { - HeaderMenu(title: "Drawing something") - } - Spacer().frame(height: 20) - toolkitView - if showLineWith == true { - sliderLineView - } - Spacer() - DrawingView(canvas: $canvas, isdraw: $isdraw, type: $type, color: $color, isColoring: $isColoring, ink: $ink) - .frame(width: drawingSize.width, height: drawingSize.height) - .border(Color.gray, width: 5) - Spacer() - colorView - .onAppear { - loadCurrentDraw() - } - Spacer() - saveView + ZStack { + Color.white.edgesIgnoringSafeArea(.all) + VStack(spacing: 10) { + if isColoring == true { + HeaderMenu(title: "Coloring Something") + } else { + HeaderMenu(title: "Drawing something") } + Spacer().frame(height: 20) + toolkitView + if showLineWith == true { + sliderLineView + } + Spacer() + DrawingView(canvas: $canvas, isdraw: $isdraw, type: $type, color: $color, isColoring: $isColoring, ink: $ink) + .frame(width: drawingSize.width, height: drawingSize.height) + .border(Color.gray, width: 5) + Spacer() + colorView + .onAppear { + loadCurrentDraw() + } + Spacer() + saveView } } } @@ -141,7 +140,7 @@ struct DrawView: View { .background(primaryColor) .cornerRadius(10) .padding(.horizontal, 20.0) - .buttonStyle(ActivityLogButtonStyle(activityDescription: "Saved a Draw")) + .buttonStyle(ActivityLogButtonStyle(activityDescription: isColoring == true ? "Coloring Draw SAVED" : "Draw SAVED")) .alert("Enter the title of the drawing", isPresented: $emptyDrawAlert) { TextField("Title", text: $title) Button("OK", action: saveImage) diff --git a/Balance/Distraction/Drawing/MandalaCollectionView.swift b/Balance/Distraction/Drawing/MandalaCollectionView.swift index 7f91db0..ea00426 100644 --- a/Balance/Distraction/Drawing/MandalaCollectionView.swift +++ b/Balance/Distraction/Drawing/MandalaCollectionView.swift @@ -11,33 +11,31 @@ struct MandalaCollectionView: View { @Binding var currentDraw: Draw @Binding var images: [Mandala] var gridItemLayout = [GridItem(.fixed(110)), GridItem(.fixed(110)), GridItem(.fixed(110))] - + var body: some View { - ActivityLogContainer { - ScrollView(.horizontal, showsIndicators: false) { - LazyHGrid(rows: gridItemLayout, alignment: .center, spacing: 10) { - ForEach(images.indices, id: \.self) { index in - NavigationLink( - destination: ActivityLogBaseView( - viewName: "Mandala Selected: " + images[index].name, - isDirectChildToContainer: true, - content: { - DrawView(currentDraw: $currentDraw, isNewDraw: true, isColoring: true) - } - ) - ) { - Image(images[index].name) - .resizable() - .scaledToFit() - .aspectRatio(contentMode: .fill) - .clipped() - .frame(width: 110, height: 110, alignment: .center) - .cornerRadius(10) - .accessibilityLabel(images[index].name) - }.simultaneousGesture(TapGesture().onEnded { - self.currentDraw.backImage = images[index].name - }) - } + ScrollView(.horizontal, showsIndicators: false) { + LazyHGrid(rows: gridItemLayout, alignment: .center, spacing: 10) { + ForEach(images.indices, id: \.self) { index in + NavigationLink( + destination: ActivityLogBaseView( + viewName: "Mandala Selected: " + images[index].name, + isDirectChildToContainer: true, + content: { + DrawView(currentDraw: $currentDraw, isNewDraw: true, isColoring: true) + } + ) + ) { + Image(images[index].name) + .resizable() + .scaledToFit() + .aspectRatio(contentMode: .fill) + .clipped() + .frame(width: 110, height: 110, alignment: .center) + .cornerRadius(10) + .accessibilityLabel(images[index].name) + }.simultaneousGesture(TapGesture().onEnded { + self.currentDraw.backImage = images[index].name + }) } } } diff --git a/Balance/Distraction/Drawing/PastEntryView.swift b/Balance/Distraction/Drawing/PastEntryView.swift index d2086b4..84840d4 100644 --- a/Balance/Distraction/Drawing/PastEntryView.swift +++ b/Balance/Distraction/Drawing/PastEntryView.swift @@ -12,25 +12,23 @@ struct PastEntryView: View { private var draw: Draw var body: some View { - ActivityLogContainer { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(draw.date.timeSinceDate(fromDate: Date())) - .font(.custom("Nunito-Bold", size: 11)) - .foregroundColor(.gray) - Spacer().frame(height: 10) - loadImages - } - Spacer() - Image(systemName: "chevron.right") - .foregroundColor(darkBlueColor) + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(draw.date.timeSinceDate(fromDate: Date())) + .font(.custom("Nunito-Bold", size: 11)) + .foregroundColor(.gray) + Spacer().frame(height: 10) + loadImages } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(20) - .background() - .cornerRadius(15) - .shadow(color: Color.black.opacity(0.1), radius: 5) + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(darkBlueColor) } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(20) + .background() + .cornerRadius(15) + .shadow(color: Color.black.opacity(0.1), radius: 5) } var loadImages: some View { diff --git a/Balance/Distraction/Gallery/LookImages/GalleryView.swift b/Balance/Distraction/Gallery/LookImages/GalleryView.swift index 7ef9b1c..54aa9d3 100644 --- a/Balance/Distraction/Gallery/LookImages/GalleryView.swift +++ b/Balance/Distraction/Gallery/LookImages/GalleryView.swift @@ -14,7 +14,7 @@ struct ImageTagView: View { @Binding var selectedCat: Category @Binding var isUpload: Bool @Binding var profile: ProfileUser - + var body: some View { Button(action: { self.isUpload = false @@ -37,7 +37,7 @@ struct ImageTagView: View { for photo in photoArray { for category in photo.category where category.name == self.selectedCategory.name { for removedPhoto in removedElements where removedPhoto.name == photo.name { - isRemoved = true + isRemoved = true } if !isRemoved { filteredCat.append(photo) @@ -68,32 +68,30 @@ struct GalleryView: View { @State var isUpload = false @State var profile = ProfileUser() let highlightArray = photoArray.filter { $0.highlight == true } - + var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Look at Pictures") - VStack(alignment: .center, spacing: 10) { - highlightsTitle - imagePaging - HStack { - categoriesTitle.padding(10) - Spacer() - if isUpload == true { - uploadButton.padding(10) - } - } - tagsView + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Look at Pictures") + VStack(alignment: .center, spacing: 10) { + highlightsTitle + imagePaging + HStack { + categoriesTitle.padding(10) Spacer() + if isUpload == true { + uploadButton.padding(10) + } } - .edgesIgnoringSafeArea(.all) + tagsView + Spacer() } - }.onAppear { - loadUser() - loadData() + .edgesIgnoringSafeArea(.all) } + }.onAppear { + loadUser() + loadData() } } diff --git a/Balance/Distraction/Gallery/LookImages/ImageView.swift b/Balance/Distraction/Gallery/LookImages/ImageView.swift index 575f379..87576e6 100644 --- a/Balance/Distraction/Gallery/LookImages/ImageView.swift +++ b/Balance/Distraction/Gallery/LookImages/ImageView.swift @@ -8,18 +8,18 @@ import SwiftUI struct HUD: View { - @ViewBuilder let content: Content - - var body: some View { - content - .padding(.horizontal, 12) - .padding(16) - .background( - Capsule() - .foregroundColor(Color.white) - .shadow(color: Color(.black).opacity(0.16), radius: 12, x: 0, y: 5) - ) - } + @ViewBuilder let content: Content + + var body: some View { + content + .padding(.horizontal, 12) + .padding(16) + .background( + Capsule() + .foregroundColor(Color.white) + .shadow(color: Color(.black).opacity(0.16), radius: 12, x: 0, y: 5) + ) + } } struct ScaleButtonStyle: ButtonStyle { @@ -29,9 +29,9 @@ struct ScaleButtonStyle: ButtonStyle { } } -// swiftlint:disable attributes struct ImageView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss var imagesArray: [Photo] @State var currentIndex = 0 @State var selected: Photo @@ -47,40 +47,38 @@ struct ImageView: View { @State var tapReturn = false @State var tapLike = false @State var tapDislike = false - + var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Look at Images") - Spacer() - tabImages - .tabViewStyle(.page(indexDisplayMode: .never)) - .onAppear(perform: { - self.selected = self.imagesArray[currentIndex] - }) - Spacer() - actionsButtons - Spacer() + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Look at Images") + Spacer() + tabImages + .tabViewStyle(.page(indexDisplayMode: .never)) + .onAppear(perform: { + self.selected = self.imagesArray[currentIndex] + }) + Spacer() + actionsButtons + Spacer() + } + if showingHUD { + HUD { + Label(strMsg, systemImage: imgMsg) } - if showingHUD { - HUD { - Label(strMsg, systemImage: imgMsg) - } - .transition(AnyTransition.move(edge: .top).combined(with: .opacity)) - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - withAnimation { - showingHUD = false - } + .transition(AnyTransition.move(edge: .top).combined(with: .opacity)) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + withAnimation { + showingHUD = false } } - .zIndex(1) } - }.onAppear { - loadUser() + .zIndex(1) } + }.onAppear { + loadUser() } } @@ -119,7 +117,7 @@ struct ImageView: View { showingHUD.toggle() self.strMsg = "Deleted!" self.imgMsg = "trash.fill" - + removeFrom(type: "FavoritesArray", name: selected.name) removeFrom(type: "RemovedArray", name: selected.name) removeFrom(type: "UploadedArray", name: selected.name) diff --git a/Balance/Distraction/Gallery/LookVideos/VideoGalleryView.swift b/Balance/Distraction/Gallery/LookVideos/VideoGalleryView.swift index 45df5a1..554ea8b 100644 --- a/Balance/Distraction/Gallery/LookVideos/VideoGalleryView.swift +++ b/Balance/Distraction/Gallery/LookVideos/VideoGalleryView.swift @@ -62,20 +62,18 @@ struct VideoGalleryView: View { let highlightArray = videoArray.filter { $0.highlight == true } var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Look Videos") - VStack(alignment: .center, spacing: 10) { - highlightsTitle - videoPaging - categoriesTitle - tagsView - Spacer() - } - .edgesIgnoringSafeArea(.all) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Look Videos") + VStack(alignment: .center, spacing: 10) { + highlightsTitle + videoPaging + categoriesTitle + tagsView + Spacer() } + .edgesIgnoringSafeArea(.all) } } } diff --git a/Balance/Distraction/Games/GamesCellView.swift b/Balance/Distraction/Games/GamesCellView.swift index 07bd4e9..3b97fc2 100644 --- a/Balance/Distraction/Games/GamesCellView.swift +++ b/Balance/Distraction/Games/GamesCellView.swift @@ -12,18 +12,16 @@ struct GamesCellView: View { var text: String var body: some View { - ActivityLogContainer { - HStack { - iconView - textView - } - .frame(maxWidth: 311, maxHeight: 120) - .foregroundColor(darkBlueColor) - .background(RoundedRectangle(cornerRadius: 20).fill(.white)) - .clipped() - .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) - .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) + HStack { + iconView + textView } + .frame(maxWidth: 311, maxHeight: 120) + .foregroundColor(darkBlueColor) + .background(RoundedRectangle(cornerRadius: 20).fill(.white)) + .clipped() + .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } var textView: some View { diff --git a/Balance/Distraction/Games/GamesView.swift b/Balance/Distraction/Games/GamesView.swift index 852de45..23e2f00 100644 --- a/Balance/Distraction/Games/GamesView.swift +++ b/Balance/Distraction/Games/GamesView.swift @@ -9,19 +9,17 @@ import SwiftUI struct GamesView: View { var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Games") - ScrollView(.vertical) { - VStack(spacing: 20) { - sudokuGame - crossoverGame - } - .padding(10) - .ignoresSafeArea(.all) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Games") + ScrollView(.vertical) { + VStack(spacing: 20) { + sudokuGame + crossoverGame } + .padding(10) + .ignoresSafeArea(.all) } } } diff --git a/Balance/Distraction/Games/GamesWebView.swift b/Balance/Distraction/Games/GamesWebView.swift index bcc7b70..bc887e6 100644 --- a/Balance/Distraction/Games/GamesWebView.swift +++ b/Balance/Distraction/Games/GamesWebView.swift @@ -11,19 +11,18 @@ struct GamesWebView: View { @StateObject var webViewStore = WebViewStore() var gameLink: String var titleGame: String - + var body: some View { - ActivityLogContainer { - HeaderMenu(title: titleGame) - WebView(webView: webViewStore.webView) - .edgesIgnoringSafeArea(.bottom) - .onAppear { - guard let sudokuLink = URL(string: gameLink) else { - return - } - self.webViewStore.webView.load(URLRequest(url: sudokuLink)) + HeaderMenu(title: titleGame) + WebView(webView: webViewStore.webView) + .edgesIgnoringSafeArea(.bottom) + .onAppear { + guard let sudokuLink = URL(string: gameLink) else { + return } - }.background(backgroundColor) + self.webViewStore.webView.load(URLRequest(url: sudokuLink)) + } + .background(backgroundColor) } init(gameLink: String, titleGame: String) { diff --git a/Balance/Distraction/Music/iOS_SDK/SpotifyView.swift b/Balance/Distraction/Music/iOS_SDK/SpotifyView.swift index c985590..3dc9b7a 100644 --- a/Balance/Distraction/Music/iOS_SDK/SpotifyView.swift +++ b/Balance/Distraction/Music/iOS_SDK/SpotifyView.swift @@ -12,10 +12,10 @@ import UIKit struct SpotifyView: UIViewControllerRepresentable { @EnvironmentObject var activityLogEntry: ActivityLogEntry - + func makeUIViewController(context: Context) -> SpotifyViewController { let spotifyViewController = SpotifyViewController.shared -// spotifyViewController.activityLogEntry = activityLogEntry + spotifyViewController.activityLogEntry = activityLogEntry return spotifyViewController } diff --git a/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift b/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift index fdc3cf9..971e402 100644 --- a/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift +++ b/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift @@ -85,8 +85,8 @@ class SpotifyViewController: UIViewController { private var lastPlayerState: SPTAppRemotePlayerState? -// var activityLogEntry: ActivityLogEntry? - + var activityLogEntry: ActivityLogEntry? + // MARK: - Subviews let stackView = UIStackView() let stackInstallView = UIStackView() @@ -104,11 +104,13 @@ class SpotifyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() layout() + // Read Boolean print("Spotify view start") } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + activityLogEntry?.addAction(actionDescription: "Opened Playing Spotify") updateViewBasedOnConnected() } @@ -119,6 +121,7 @@ class SpotifyViewController: UIViewController { appRemote.playerAPI?.pause(nil) } } + activityLogEntry?.endLog(actionDescription: "Closed Playing Spotify") } @objc @@ -443,6 +446,8 @@ extension SpotifyViewController: UITableViewDelegate, UITableViewDataSource { func reconnect(uri: String) { if self.isOnScreen { + UserDefaults.standard.set(true, forKey: StorageKeys.spotifyConnect) + // activityLogEntry?.addAction(actionDescription: "Connecting Spotify") self.currentUri = uri configuration.playURI = self.currentUri diff --git a/Balance/Distraction/Music/iOS_SDK/TrackCellView.swift b/Balance/Distraction/Music/iOS_SDK/TrackCellView.swift index 70587df..7f2593e 100644 --- a/Balance/Distraction/Music/iOS_SDK/TrackCellView.swift +++ b/Balance/Distraction/Music/iOS_SDK/TrackCellView.swift @@ -11,26 +11,24 @@ struct TrackCellView: View { var image: String var text: String var duration: String - + var body: some View { - ActivityLogContainer { - HStack { - iconView - VStack { - Spacer() - textView -// durationView - Spacer() - } + HStack { + iconView + VStack { + Spacer() + textView + // durationView + Spacer() } - .frame(maxWidth: 311, maxHeight: 120) - .foregroundColor(darkBlueColor) - .background(RoundedRectangle(cornerRadius: 20).fill(.white)) - .clipped() - .frame(height: 120.0) - .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) - .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } + .frame(maxWidth: 311, maxHeight: 120) + .foregroundColor(darkBlueColor) + .background(RoundedRectangle(cornerRadius: 20).fill(.white)) + .clipped() + .frame(height: 120.0) + .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } var textView: some View { diff --git a/Balance/Fealing/FeelingView.swift b/Balance/Fealing/FeelingView.swift index 939ffce..e54171b 100644 --- a/Balance/Fealing/FeelingView.swift +++ b/Balance/Fealing/FeelingView.swift @@ -9,19 +9,17 @@ import SwiftUI struct FeelingView: View { var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Feeling learning") - ScrollView(.vertical) { - VStack(spacing: 20) { - guessOption - moodOption - } - .padding(10) - .ignoresSafeArea(.all) + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Feeling learning") + ScrollView(.vertical) { + VStack(spacing: 20) { + guessOption + moodOption } + .padding(10) + .ignoresSafeArea(.all) } } } @@ -37,10 +35,10 @@ struct FeelingView: View { } ) ) { - CellView(image: "guessIcon", text: "Guess the emotion") + DistractionCellView(image: "guessIcon", text: "Guess the emotion", pointVal: "5") } } - + var moodOption: some View { NavigationLink( destination: ActivityLogBaseView( @@ -51,7 +49,7 @@ struct FeelingView: View { } ) ) { - CellView(image: "moodIcon", text: "How is your mood") + DistractionCellView(image: "moodIcon", text: "How is your mood", pointVal: "5") } } } diff --git a/Balance/Fealing/Guess/GuessView.swift b/Balance/Fealing/Guess/GuessView.swift index afe7ac5..3c83944 100644 --- a/Balance/Fealing/Guess/GuessView.swift +++ b/Balance/Fealing/Guess/GuessView.swift @@ -7,9 +7,9 @@ import SwiftUI -// swiftlint:disable attributes struct GuessView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss @State var selected = 10 @State var questionIndex = 0 @State var stopUserInteraction = false @@ -22,35 +22,33 @@ struct GuessView: View { GridItem(.flexible()), GridItem(.flexible()) ] - + var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Feeling learning") - Spacer() - ZStack(alignment: .topLeading) { - questionNumber - imageView - } - Spacer() - titleText - Spacer() - optionsButtons + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Feeling learning") + Spacer() + ZStack(alignment: .topLeading) { + questionNumber + imageView } + Spacer() + titleText + Spacer() + optionsButtons } - .onAppear(perform: { - questions = questionArray.prefix(cantAnswer).shuffled() - }) - .disabled(stopUserInteraction) - .alert("You got \(correctAnswer)/\(cantAnswer) right on the first try!", isPresented: $showingAlert) { - Button("Close", role: .cancel) { - correctAnswer = 0 - firstTry = true - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - dismiss() - } + } + .onAppear(perform: { + questions = questionArray.prefix(cantAnswer).shuffled() + }) + .disabled(stopUserInteraction) + .alert("You got \(correctAnswer)/\(cantAnswer) right on the first try!", isPresented: $showingAlert) { + Button("Close", role: .cancel) { + correctAnswer = 0 + firstTry = true + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { + dismiss() } } } diff --git a/Balance/Fealing/Mood/FacesScreenView.swift b/Balance/Fealing/Mood/FacesScreenView.swift index c8626b7..86e6be3 100644 --- a/Balance/Fealing/Mood/FacesScreenView.swift +++ b/Balance/Fealing/Mood/FacesScreenView.swift @@ -74,16 +74,14 @@ struct FacesScreenView: View { ] var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack(spacing: 30) { - HeaderMenu(title: "Feeling learning") - titleText - gridView - .padding(.horizontal, 40.0) - Spacer() - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack(spacing: 30) { + HeaderMenu(title: "Feeling learning") + titleText + gridView + .padding(.horizontal, 40.0) + Spacer() } } } diff --git a/Balance/Fealing/Mood/MoodEditorView.swift b/Balance/Fealing/Mood/MoodEditorView.swift index b16baba..d43ba2f 100644 --- a/Balance/Fealing/Mood/MoodEditorView.swift +++ b/Balance/Fealing/Mood/MoodEditorView.swift @@ -7,9 +7,9 @@ import SwiftUI -// swiftlint:disable attributes struct MoodEditorView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss @EnvironmentObject var store: NoteStore @Binding var currentNote: Note @State private var title = "" @@ -19,26 +19,24 @@ struct MoodEditorView: View { @State private var emptyNoteAlert = false var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Feeling learning") - Spacer().frame(height: 20) - titleText - TextField("Note Title", text: $title) - .font(.custom("Nunito-Bold", size: 18)) - .padding() - TextEditor(text: $text) - .font(.custom("Nunito", size: 16)) - .border(.black.opacity(0.2), width: 1) - .padding() - saveButton - }.onAppear { - self.title = currentNote.title - self.text = currentNote.text - self.id = currentNote.id - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Feeling learning") + Spacer().frame(height: 20) + titleText + TextField("Note Title", text: $title) + .font(.custom("Nunito-Bold", size: 18)) + .padding() + TextEditor(text: $text) + .font(.custom("Nunito", size: 16)) + .border(.black.opacity(0.2), width: 1) + .padding() + saveButton + }.onAppear { + self.title = currentNote.title + self.text = currentNote.text + self.id = currentNote.id } } } diff --git a/Balance/Home/CellView.swift b/Balance/Home/CellView.swift index b2af5bd..c828f77 100644 --- a/Balance/Home/CellView.swift +++ b/Balance/Home/CellView.swift @@ -12,18 +12,16 @@ struct CellView: View { var text: String var body: some View { - ActivityLogContainer { - HStack { - iconView - textView - } - .frame(maxWidth: 311, maxHeight: 120) - .foregroundColor(darkBlueColor) - .background(RoundedRectangle(cornerRadius: 20).fill(.white)) - .clipped() - .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) - .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) + HStack { + iconView + textView } + .frame(maxWidth: 311, maxHeight: 120) + .foregroundColor(darkBlueColor) + .background(RoundedRectangle(cornerRadius: 20).fill(.white)) + .clipped() + .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } var textView: some View { diff --git a/Balance/Home/Home.swift b/Balance/Home/Home.swift index 1938e0a..6caebee 100644 --- a/Balance/Home/Home.swift +++ b/Balance/Home/Home.swift @@ -16,7 +16,7 @@ struct HomeView: View { // @EnvironmentObject var firebaseAccountConfiguration: FirebaseAccountConfiguration @EnvironmentObject var authModel: AuthViewModel @State var showMe = false - + @State var profile = ProfileUser() var clipsToBounds = false var body: some View { @@ -26,21 +26,7 @@ struct HomeView: View { NavigationStack { VStack(spacing: 0) { HeaderHome() - ZStack(alignment: .bottomLeading) { - ScrollView(.vertical) { - VStack(spacing: 20) { - distractOption - chillOption - fealingLearningOption - diaryOption - } - .padding(20) - .ignoresSafeArea(.all) - } - .zIndex(1) - Spacer() - cloudImage.zIndex(-1) - } + menuOptions Spacer() } .navigationTitle("") @@ -54,6 +40,11 @@ struct HomeView: View { #endif } } + .onChange(of: authModel.profile) { _ in + withAnimation(.easeInOut(duration: 1.0)) { + loadUser() + } + } } } @@ -88,6 +79,38 @@ struct HomeView: View { } } + var menuOptions: some View { + ZStack(alignment: .bottomTrailing) { + ZStack(alignment: .bottomLeading) { + ScrollView(.vertical) { + VStack(spacing: 20) { + distractOption + chillOption + fealingLearningOption + diaryOption + } + .padding(20) + .ignoresSafeArea(.all) + } + .zIndex(1) + Spacer() + cloudImage.zIndex(-1) + } + accesoryImage.zIndex(2) + } + } + + var accesoryImage: some View { + Image(profile.accesory) + .resizable() + .accessibilityLabel("acc_icon") + .scaledToFit() + .clipped() + .frame(width: 150, height: 150) + .background(Color.clear) + .offset(x: -30, y: -10) + } + var cloudImage: some View { Image("cloud") .accessibilityLabel("cloud") @@ -181,6 +204,30 @@ struct HomeView: View { NavView(image: "distractMeIcon", text: "Distract me") } } + + func loadUser() { +#if !DEMO + UserProfileRepository.shared.fetchCurrentProfile { profileUser, error in + if let error = error { + print("Error while fetching the user profile: \(error)") + return + } else { + print("User: " + (profileUser?.description() ?? "-")) + self.profile = profileUser + } + } +#else + UserProfileRepositoryToLocal.shared.fetchCurrentProfile { profileUser, error in + if let error = error { + print("Error while fetching the user profile: \(error)") + return + } else { + print("User: " + (profileUser?.description() ?? "-")) + self.profile = profileUser ?? ProfileUser() + } + } +#endif + } } #if DEBUG diff --git a/Balance/Home/LocationView.swift b/Balance/Home/LocationView.swift index e47dbb7..9fd150f 100644 --- a/Balance/Home/LocationView.swift +++ b/Balance/Home/LocationView.swift @@ -12,36 +12,34 @@ struct LocationView: View { var clipsToBounds = false var body: some View { - ActivityLogContainer { - VStack(spacing: 20) { - Spacer() - titleView - Spacer() - NavigationLink( - destination: ActivityLogBaseView( - viewName: "Hospital Selection", - isDirectChildToContainer: true, - content: { - HomeView() - } - ) - ) { - NavView(image: "hospitalIcon", text: "Hospital") - } - NavigationLink( - destination: ActivityLogBaseView( - viewName: "Home Selection", - isDirectChildToContainer: true, - content: { - HomeView() - } - ) - ) { - NavView(image: "homeIcon", text: "Home") - } - Spacer() - nextButtonView + VStack(spacing: 20) { + Spacer() + titleView + Spacer() + NavigationLink( + destination: ActivityLogBaseView( + viewName: "Hospital Selection", + isDirectChildToContainer: true, + content: { + HomeView() + } + ) + ) { + NavView(image: "hospitalIcon", text: "Hospital") } + NavigationLink( + destination: ActivityLogBaseView( + viewName: "Home Selection", + isDirectChildToContainer: true, + content: { + HomeView() + } + ) + ) { + NavView(image: "homeIcon", text: "Home") + } + Spacer() + nextButtonView }.background(backgroundColor) } diff --git a/Balance/Home/NavigationView.swift b/Balance/Home/NavigationView.swift index 5fe5075..da4947f 100644 --- a/Balance/Home/NavigationView.swift +++ b/Balance/Home/NavigationView.swift @@ -11,30 +11,28 @@ import SwiftUI struct NavView: View { var image: String var text: String - + var body: some View { - ActivityLogContainer { - HStack { - Text(text) - .font(.custom("Nunito-Bold", size: 25)) - .lineLimit(2) - .multilineTextAlignment(.leading) - .frame(maxWidth: .infinity, alignment: .leading) - .frame(height: 80) - Image(image) - .resizable() - .scaledToFit() - .accessibilityLabel(Text(text)) - .frame(maxWidth: .infinity) - } - .padding(EdgeInsets(top: 24, leading: 24, bottom: 24, trailing: 0)) - .frame(maxWidth: 311, maxHeight: 114) - .foregroundColor(darkBlueColor) - .background(RoundedRectangle(cornerRadius: 20).fill(.white)) - .clipped() - .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) - .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) + HStack { + Text(text) + .font(.custom("Nunito-Bold", size: 25)) + .lineLimit(2) + .multilineTextAlignment(.leading) + .frame(maxWidth: .infinity, alignment: .leading) + .frame(height: 80) + Image(image) + .resizable() + .scaledToFit() + .accessibilityLabel(Text(text)) + .frame(maxWidth: .infinity) } + .padding(EdgeInsets(top: 24, leading: 24, bottom: 24, trailing: 0)) + .frame(maxWidth: 311, maxHeight: 114) + .foregroundColor(darkBlueColor) + .background(RoundedRectangle(cornerRadius: 20).fill(.white)) + .clipped() + .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } } diff --git a/Balance/Login/AuthViewModel.swift b/Balance/Login/AuthViewModel.swift index e9866b0..ae451bf 100644 --- a/Balance/Login/AuthViewModel.swift +++ b/Balance/Login/AuthViewModel.swift @@ -104,6 +104,7 @@ final class AuthViewModel: ObservableObject { country: "", phone: "", avatar: "avatar_" + String(Int.random(in: 1..<7)), + accesory: "", password: "" ) @@ -141,6 +142,7 @@ final class AuthViewModel: ObservableObject { country: userData.country, phone: userData.phone, avatar: userData.avatar, + accesory: userData.accesory, password: "" ) diff --git a/Balance/Login/OnboardingFlow.swift b/Balance/Login/OnboardingFlow.swift index 2ffe8ec..4f67317 100644 --- a/Balance/Login/OnboardingFlow.swift +++ b/Balance/Login/OnboardingFlow.swift @@ -33,7 +33,7 @@ public struct OnboardingFlow: View { case .signUp: SignUpView(onboardingSteps: $onboardingSteps) case .avatar: - AvatarSelectionView(onboardingSteps: $onboardingSteps, firstLoad: true) + AvatarSelectionView(onboardingSteps: $onboardingSteps, firstLoad: true, accesoryLoad: false) } } .navigationBarTitleDisplayMode(.inline) diff --git a/Balance/Login/ProfileUser.swift b/Balance/Login/ProfileUser.swift index 8b939bf..ceb4326 100644 --- a/Balance/Login/ProfileUser.swift +++ b/Balance/Login/ProfileUser.swift @@ -20,6 +20,7 @@ struct ProfileUser: Codable, Equatable, Hashable, Identifiable { let country: String let phone: String var avatar: String + var accesory: String let password: String init() { @@ -31,6 +32,7 @@ struct ProfileUser: Codable, Equatable, Hashable, Identifiable { self.country = "" self.phone = "" self.avatar = "" + self.accesory = "" self.password = "" } @@ -43,6 +45,7 @@ struct ProfileUser: Codable, Equatable, Hashable, Identifiable { country: String, phone: String, avatar: String, + accesory: String, password: String ) { self.id = id @@ -53,11 +56,20 @@ struct ProfileUser: Codable, Equatable, Hashable, Identifiable { self.country = country self.phone = phone self.avatar = avatar + self.accesory = accesory self.password = password } func description() -> String { - let description = id + "-" + displayName + "-" + email + "-" + parentEmail + "-" + birthday + "-" + country + "-" + phone + "-" + avatar + let description = id + "-" + + displayName + "-" + + email + "-" + + parentEmail + "-" + + birthday + "-" + + country + "-" + + phone + "-" + + avatar + "-" + + accesory return description } } diff --git a/Balance/Login/SignUpView.swift b/Balance/Login/SignUpView.swift index 2f0fdc2..78cd14b 100644 --- a/Balance/Login/SignUpView.swift +++ b/Balance/Login/SignUpView.swift @@ -13,14 +13,14 @@ import Onboarding import SwiftUI // swiftlint: disable type_body_length -// swiftlint:disable attributes struct SignUpView: View { @EnvironmentObject var account: Account @EnvironmentObject private var authModel: AuthViewModel @EnvironmentObject var firebaseAccountConfiguration: FirebaseAccountConfiguration @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false - @Environment(\.dismiss) private var dismiss + @Environment(\.dismiss) + private var dismiss @Binding private var onboardingSteps: [OnboardingFlow.Step] @State private var displayName: String = "" @State private var email: String = "" @@ -95,6 +95,7 @@ struct SignUpView: View { country: country.name, phone: phone, avatar: "", + accesory: "", password: password ) ) diff --git a/Balance/NavBar/HeaderHome.swift b/Balance/NavBar/HeaderHome.swift index 58f93d9..c46c009 100644 --- a/Balance/NavBar/HeaderHome.swift +++ b/Balance/NavBar/HeaderHome.swift @@ -14,13 +14,19 @@ import FirebaseAccount public struct HeaderHome: View { @AppStorage("fromSOS") var fromSOS = false + @SceneStorage(StorageKeys.onboardingFlowStep) + private var onboardingSteps: [OnboardingFlow.Step] = [] @EnvironmentObject var authModel: AuthViewModel + @EnvironmentObject var banerManager: PresentBannerManager @State private var showingHomeSheet = false @State private var showingPointsSheet = false @State private var showingAvatarSheet = false @State private var displayName = "" @State private var avatar = "" @State private var userId = "" + @State private var coins = 0 + @State private var showingHUD = false + private var quotes = [ "“We cannot solve problems with the kind of thinking we employed when we came up with them.” — Albert Einstein", "“Learn as if you will live forever, live like you will die tomorrow.” — Mahatma Gandhi", @@ -32,16 +38,18 @@ public struct HeaderHome: View { ] public var body: some View { - VStack(spacing: 0) { - if UIDevice.current.hasNotch { - Spacer().frame(height: notch) - } - headerView - Spacer() -// buttonsView -// Spacer() -// quotasView - Spacer() + ZStack { + VStack(spacing: 0) { + if UIDevice.current.hasNotch { + Spacer().frame(height: notch) + } + headerView + Spacer() + buttonsView + // Spacer() + // quotasView + Spacer() + }.zIndex(-1) } .frame(maxWidth: .infinity) .ignoresSafeArea(edges: .all) @@ -67,46 +75,66 @@ public struct HeaderHome: View { } } } + .onReceive(NotificationCenter.default.publisher(for: Notification.Name.coinsUpdate)) { _ in + coins = UserDefaults.standard.integer(forKey: "\(userId)_coins") + coins += coinsValue + UserDefaults.standard.set(coins, forKey: "\(userId)_coins") + self.banerManager.banner = .init( + title: "Coins!", + message: "You have earned \(coinsValue) coins!!" + ) + } + .onReceive(NotificationCenter.default.publisher(for: Notification.Name.coinsRefresh)) { _ in + coins = UserDefaults.standard.integer(forKey: "\(userId)_coins") + } + .onReceive(NotificationCenter.default.publisher(for: Notification.Name.coinsAlert)) { _ in + self.banerManager.banner = .init( + title: "Coins!", + message: "You need moare coins to buy this accessory!!" + ) + } } var buttonsView: some View { - HStack { - Button(action: { - showingHomeSheet.toggle() - print("home") - }) { - homeButton - } - .buttonStyle(PlainButtonStyle()) - // .sheet(isPresented: $showingHomeSheet) { - // LocationView() - // } - .shadow(color: .gray, radius: 2, x: 0, y: 1) - .padding(.horizontal, 5.0) + HStack(alignment: .top) { +// Button(action: { +// showingHomeSheet.toggle() +// print("home") +// }) { +// homeButton +// } +// .buttonStyle(PlainButtonStyle()) +// .sheet(isPresented: $showingHomeSheet) { +// LocationView() +// } +// .shadow(color: .gray, radius: 2, x: 0, y: 1) +// .padding(.horizontal, 5.0) + Button(action: { - showingPointsSheet.toggle() - print("stars!") + showingAvatarSheet.toggle() + print("avatarView") }) { pointsButton + }.sheet(isPresented: $showingAvatarSheet) { + AvatarSelectionView(onboardingSteps: $onboardingSteps, firstLoad: false, accesoryLoad: true).environmentObject(authModel) } .buttonStyle(PlainButtonStyle()) - // .sheet(isPresented: $showingPointsSheet) { - // PointsView() - // } .shadow(color: .gray, radius: 2, x: 0, y: 1) - .padding(.horizontal, 5.0) + .offset(y: -10) } + .padding(5.0) } var pointsButton: some View { ZStack { - Text("0") + Text("\(coins)") .font(.custom("Nunito-Light", size: 12)) .frame(width: 100, height: 30) .foregroundColor(Color.black) .background(Color.white.opacity(0.8)) .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous)) - Image("pointsStarIcon").accessibilityLabel("pointsStarIcon") + Image("pointsStarIcon") + .accessibilityLabel("pointsStarIcon") .padding(.trailing, 65.0) } } @@ -236,6 +264,7 @@ public struct HeaderHome: View { self.displayName = authModel.profile?.displayName ?? "" self.avatar = authModel.profile?.avatar ?? "" self.userId = authModel.profile?.id ?? "00000" + coins = UserDefaults.standard.integer(forKey: "\(profileUser.id)_coins") } } #else @@ -250,6 +279,7 @@ public struct HeaderHome: View { self.avatar = authModel.profile?.avatar ?? "avatar_1" self.userId = authModel.profile?.id ?? "00000" + self.coins = UserDefaults.standard.integer(forKey: "\(self.userId)_coins") } } #endif diff --git a/Balance/NavBar/HeaderMenu.swift b/Balance/NavBar/HeaderMenu.swift index 057b7fb..b64b301 100644 --- a/Balance/NavBar/HeaderMenu.swift +++ b/Balance/NavBar/HeaderMenu.swift @@ -8,10 +8,10 @@ import SwiftUI -// swiftlint:disable attributes struct HeaderMenu: View { @State private var showingSOSSheet = false - @Environment(\.presentationMode) var presentationMode + @Environment(\.presentationMode) + var presentationMode @AppStorage("fromSOS") var fromSOS = false var title: String diff --git a/Balance/Profile/Accesory.swift b/Balance/Profile/Accesory.swift index 93d4a51..96bfd26 100644 --- a/Balance/Profile/Accesory.swift +++ b/Balance/Profile/Accesory.swift @@ -11,4 +11,5 @@ public struct Accesory: Codable, Equatable, Hashable, Identifiable { public var id = UUID() var name: String var state = false + var value = 0 } diff --git a/Balance/Profile/AccesoryArray.swift b/Balance/Profile/AccesoryArray.swift new file mode 100644 index 0000000..d7cc494 --- /dev/null +++ b/Balance/Profile/AccesoryArray.swift @@ -0,0 +1,35 @@ +// +// AccesoryArray.swift +// Balance +// +// Created by Gonzalo Perisset on 07/08/2023. +// + +import SwiftUI + +class AccesoryManager: ObservableObject { + // @Published var accesories = (1...21).map { Accesory(name: "acc_\($0)") } + @Published var accesories: [Accesory] = [ + Accesory(name: "acc_1", value: 25), + Accesory(name: "acc_2", value: 50), + Accesory(name: "acc_3", value: 75), + Accesory(name: "acc_4", value: 100), + Accesory(name: "acc_5", value: 500), + Accesory(name: "acc_6", value: 100), + Accesory(name: "acc_7", value: 150), + Accesory(name: "acc_8", value: 300), + Accesory(name: "acc_9", value: 500), + Accesory(name: "acc_10", value: 200), + Accesory(name: "acc_11", value: 100), + Accesory(name: "acc_12", value: 200), + Accesory(name: "acc_13", value: 300), + Accesory(name: "acc_14", value: 200), + Accesory(name: "acc_15", value: 300), + Accesory(name: "acc_16", value: 100), + Accesory(name: "acc_17", value: 150), + Accesory(name: "acc_18", value: 150), + Accesory(name: "acc_19", value: 100), + Accesory(name: "acc_20", value: 100), + Accesory(name: "acc_21", value: 100) + ] +} diff --git a/Balance/Profile/AccesoryView.swift b/Balance/Profile/AccesoryView.swift index cfdac82..9c1d537 100644 --- a/Balance/Profile/AccesoryView.swift +++ b/Balance/Profile/AccesoryView.swift @@ -10,6 +10,9 @@ import SwiftUI struct AccesoryView: View { @Binding var item: Accesory @Binding var selectedItem: Accesory.ID? + @Binding var selectedNameItem: String? + @State var userCoins = 0 + @State var userId = "" var body: some View { ZStack(alignment: .center) { @@ -17,17 +20,46 @@ struct AccesoryView: View { .resizable(capInsets: EdgeInsets(top: 0.0, leading: 0.0, bottom: 0.0, trailing: 0.0)) .scaledToFit() .accessibilityLabel(item.name) - Image((item.id == selectedItem) ? "checkFill" : "check") - .resizable() - .frame(width: 40, height: 40) - .clipped() - .offset(x: -50, y: -50) - .accessibilityLabel("avatarCheck") + if userCoins >= item.value { + Image((item.name == selectedNameItem) ? "checkFill" : "check") + .resizable() + .frame(width: 40, height: 40) + .clipped() + .offset(x: -50, y: -50) + .accessibilityLabel("avatarCheck") + Label("\(item.value)", image: "pointsStarIcon") + .padding(5) + .font(.custom("Montserrat-SemiBold", size: 17)) + .foregroundColor(.gray) + .background(Color.white.opacity(0.6)) + .clipShape(Capsule()) + .shadow(color: .gray, radius: 5) + .offset(x: 50, y: -50) + } else { + Image("lock") + .resizable() + .scaledToFit() + .frame(width: 40, height: 40) + .clipped() + .offset(x: -50, y: -50) + .accessibilityLabel("lock") + Label("\(item.value)", image: "pointsStarIcon") + .padding(5) + .font(.custom("Montserrat-SemiBold", size: 17)) + .foregroundColor(.gray) + .background(Color.white.opacity(0.6)) + .clipShape(Capsule()) + .shadow(color: .gray, radius: 5) + } } .padding(15.0) .frame(maxWidth: 100, maxHeight: 100) .foregroundColor(darkBlueColor) .background(RoundedRectangle(cornerRadius: 20).fill(.white)) .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .onAppear(perform: { + userId = UserDefaults.standard.string(forKey: "lastPatient") ?? "0" + userCoins = UserDefaults.standard.integer(forKey: "\(userId)_coins") + }) } } diff --git a/Balance/Profile/AvatarPreviewView.swift b/Balance/Profile/AvatarPreviewView.swift index 946ebd4..57f3d62 100644 --- a/Balance/Profile/AvatarPreviewView.swift +++ b/Balance/Profile/AvatarPreviewView.swift @@ -11,10 +11,10 @@ import class FHIR.FHIR import Onboarding import SwiftUI -// swiftlint:disable attributes +// swiftlint:disable all struct AvatarPreviewView: View { - @Environment(\.dismiss) private var dismiss - @EnvironmentObject var firebaseAccountConfiguration: FirebaseAccountConfiguration + @Environment(\.dismiss) + private var dismiss @EnvironmentObject var authModel: AuthViewModel @Binding private var onboardingSteps: [OnboardingFlow.Step] @Binding private var avatarSelection: Avatar @@ -22,39 +22,40 @@ struct AvatarPreviewView: View { @State private var profile = ProfileUser() @State private var loading = false private var firstLoad: Bool + private var accesoryBuy: Bool var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - Spacer().frame(height: 50) - titlePreview - Spacer() - avatarSelected - Spacer() - saveButton - cancelButton - } - if loading { - loadingView - .ignoresSafeArea() - } - } - .disabled(loading) - .onAppear { - authModel.listenAuthentificationState() - self.profile = authModel.profile ?? ProfileUser() + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + Spacer().frame(height: 50) + titlePreview + Spacer() + avatarSelected + Spacer() + saveButton + cancelButton } - .onChange(of: authModel.profile ?? ProfileUser()) { profile in - updateData(profile: profile) + if loading { + loadingView + .ignoresSafeArea() } - .onChange(of: authModel.authError) { value in - if !value.isEmpty { - loading = false - // self.alertMessage = value - // self.showingAlert = true - } + } + .disabled(loading) + .onAppear { + loadUser() +#if !DEMO + authModel.listenAuthentificationState() +#endif + } + .onChange(of: authModel.profile ?? ProfileUser()) { profile in + updateData(profile: profile) + } + .onChange(of: authModel.authError) { value in + if !value.isEmpty { + loading = false + // self.alertMessage = value + // self.showingAlert = true } } } @@ -86,21 +87,57 @@ struct AvatarPreviewView: View { .clipped() .accessibilityLabel("star2") .offset(x: -100, y: -50) - Image(avatarSelection.name) - .resizable() - .scaledToFit() - .frame(width: 200, height: 200) - .clipped() - .accessibilityLabel("avatarPreview") - // if !firstLoad { - // Image(accesorySelection?.name ?? "acc_1") - // .resizable() - // .scaledToFit() - // .frame(width: 130, height: 130) - // .clipped() - // .accessibilityLabel("accesoryPreview") - // .offset(x: 80, y: 80) - // } + if accesoryBuy { + Image(profile.avatar) + .resizable() + .scaledToFit() + .frame(width: 200, height: 200) + .clipped() + .accessibilityLabel("avatarPreview") + } else { + if avatarSelection.name.isEmpty { + Image(profile.avatar) + .resizable() + .scaledToFit() + .frame(width: 200, height: 200) + .clipped() + .accessibilityLabel("avatarPreview") + } else { + Image(avatarSelection.name) + .resizable() + .scaledToFit() + .frame(width: 200, height: 200) + .clipped() + .accessibilityLabel("avatarPreview") + } + } + if !firstLoad { + if accesorySelection.name.isEmpty { + Image(profile.accesory) + .resizable() + .scaledToFit() + .frame(width: 130, height: 130) + .clipped() + .offset(x: 80, y: 80) + .accessibilityLabel("accesoryPreview") + } else { + Image(accesorySelection.name) + .resizable() + .scaledToFit() + .frame(width: 130, height: 130) + .clipped() + .offset(x: 80, y: 80) + .accessibilityLabel("accesoryPreview") + } + +// Image(accesorySelection.name) +// .resizable() +// .scaledToFit() +// .frame(width: 130, height: 130) +// .clipped() +// .accessibilityLabel("accesoryPreview") +// .offset(x: 80, y: 80) + } Image("stars1") .resizable() .frame(width: 50.0, height: 50.0) @@ -158,11 +195,12 @@ struct AvatarPreviewView: View { .padding(.horizontal, 20.0) } - init(onboardingSteps: Binding<[OnboardingFlow.Step]>, avatarSelection: Binding, accesorySelection: Binding, firstLoad: Bool) { + init(onboardingSteps: Binding<[OnboardingFlow.Step]>, avatarSelection: Binding, accesorySelection: Binding, firstLoad: Bool, accesoryBuy: Bool) { self._onboardingSteps = onboardingSteps self._avatarSelection = avatarSelection self._accesorySelection = accesorySelection self.firstLoad = firstLoad + self.accesoryBuy = accesoryBuy } func updateData(profile: ProfileUser) { @@ -170,11 +208,11 @@ struct AvatarPreviewView: View { onboardingSteps.remove(at: 1) onboardingSteps.remove(at: 0) } else { - withAnimation(.easeInOut(duration: 1.0)) { - self.profile = profile - loading = false - } - dismiss() +// withAnimation(.easeInOut(duration: 1.0)) { +// self.profile = profile +// loading = false +// } +// NavigationUtil.dismiss(2) } } @@ -191,28 +229,61 @@ struct AvatarPreviewView: View { return ProfileUser() } - func updateLocalProfile() { - UserProfileRepositoryToLocal.shared.fetchCurrentProfile { profileUser, error in + func loadUser() { +#if !DEMO + UserProfileRepository.shared.fetchCurrentProfile { profileUser, error in if let error = error { - loading = false print("Error while fetching the user profile: \(error)") return } else { print("User: " + (profileUser?.description() ?? "-")) - var loadExistenceProfile = profileUser ?? ProfileUser() - loadExistenceProfile.avatar = avatarSelection.name - UserProfileRepositoryToLocal.shared.createProfile(profile: loadExistenceProfile) { profile, error in - loading = false - if let error = error { - print("Error while fetching the user profile: \(error)") - return - } else { - self.profile = profile ?? ProfileUser() - authModel.profile = profile - print("User: " + (profile?.description() ?? "-")) - NavigationUtil.popToRootView() - } - } + authModel.profile = profileUser + self.profile = profileUser + } + } +#else + self.profile = authModel.profile ?? ProfileUser() +#endif + } + + func updateLocalProfile() { + print("User: " + profile.description()) + if avatarSelection.name != "" { + profile.avatar = avatarSelection.name + } + if accesorySelection.name != "" { + profile.accesory = accesorySelection.name + } + +// if accesoryBuy { +// if accesorySelection.name == "" { +// if !profile.accesory.isEmpty { +// profile.accesory = "" +// } +// } +// } + + var coins = UserDefaults.standard.integer(forKey: "\(self.profile.id)_coins") + coins -= accesorySelection.value + + if coins < 0 { + print("No coins to buy accesory") + NotificationCenter.default.post(name: Notification.Name.coinsAlert, object: nil) + return + } + + UserProfileRepositoryToLocal.shared.createProfile(profile: profile) { profile, error in + loading = false + if let error = error { + print("Error while fetching the user profile: \(error)") + return + } else { + UserDefaults.standard.set(coins, forKey: "\(self.profile.id)_coins") + NotificationCenter.default.post(name: Notification.Name.coinsRefresh, object: nil) + self.profile = profile ?? ProfileUser() + authModel.profile = profile + print("User: " + (profile?.description() ?? "-")) + NavigationUtil.dismiss(2) } } } diff --git a/Balance/Profile/AvatarSelectionView.swift b/Balance/Profile/AvatarSelectionView.swift index 03fe7a9..a57cca1 100644 --- a/Balance/Profile/AvatarSelectionView.swift +++ b/Balance/Profile/AvatarSelectionView.swift @@ -11,48 +11,76 @@ class AvatarManager: ObservableObject { @Published var avatars = (1...6).map { Avatar(name: "avatar_\($0)") } } -class AccesoryManager: ObservableObject { - @Published var accesories = (1...4).map { Accesory(name: "acc_\($0)") } -} - -// swiftlint:disable attributes struct AvatarSelectionView: View { @EnvironmentObject private var authModel: AuthViewModel - @Environment(\.dismiss) private var dismiss + @Environment(\.dismiss) + private var dismiss @State private var showingAvatarPreviewSheet = false @ObservedObject var avatarManager = AvatarManager() @State private var avatarSelection: Avatar.ID? + @State private var avatarNameSelection: String? @State private var avatarSelected = Avatar(name: "") @ObservedObject var accesoryManager = AccesoryManager() @State private var accesorySelection: Accesory.ID? + @State private var accesoryNameSelection: String? @State private var accesorySelected = Accesory(name: "") @Binding private var onboardingSteps: [OnboardingFlow.Step] + @State private var profile = ProfileUser() + @State private var userCoins = 0 var firstLoad: Bool + var accesoryLoad: Bool private var gridItemLayout = [GridItem(.fixed(150)), GridItem(.fixed(150))] var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - ScrollView { + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + ScrollView { + if !accesoryLoad { Spacer().frame(height: 50) avatarListView - // if !firstLoad { - // Spacer().frame(height: 50) - // accesoryListView - // } } + if !firstLoad { + Spacer().frame(height: 50) + accesoryListView + } + } + saveButton + }.sheet(isPresented: $showingAvatarPreviewSheet) { + AvatarPreviewView( + onboardingSteps: $onboardingSteps, + avatarSelection: $avatarSelected, + accesorySelection: $accesorySelected, + firstLoad: firstLoad, + accesoryBuy: accesoryLoad + ) + } + .onAppear { + self.profile = authModel.profile ?? ProfileUser() + userCoins = UserDefaults.standard.integer(forKey: "\(self.profile.id)_coins") + self.avatarNameSelection = self.profile.avatar + self.accesoryNameSelection = self.profile.accesory + } + } + } + + var saveButton: some View { + Group { + if accesoryLoad { + let minElement = accesoryManager.accesories.min(by: { lhs, rhs in + if lhs.value < rhs.value { + return true + } else { + return false + } + }) + + if userCoins >= minElement?.value ?? 25 { selectButton.background(.clear) - }.sheet(isPresented: $showingAvatarPreviewSheet) { - AvatarPreviewView( - onboardingSteps: $onboardingSteps, - avatarSelection: $avatarSelected, - accesorySelection: $accesorySelected, - firstLoad: firstLoad - ) } + } else { + selectButton.background(.clear) } } } @@ -63,14 +91,16 @@ struct AvatarSelectionView: View { .foregroundColor(violetColor) .font(.custom("Nunito-Bold", size: 34)) Spacer().frame(height: 50) + LazyVGrid(columns: gridItemLayout, spacing: 40) { ForEach($avatarManager.avatars) { $item in - AvatarView(item: $item, selectedItem: $avatarSelection) + AvatarView(item: $item, selectedItem: $avatarSelection, selectedNameItem: $avatarNameSelection) .onTapGesture { if let ndx = avatarManager.avatars.firstIndex(where: { $0.id == avatarSelection }) { avatarManager.avatars[ndx].state = false } avatarSelection = item.id + avatarNameSelection = item.name item.state = true avatarSelected = item } @@ -82,20 +112,26 @@ struct AvatarSelectionView: View { var accesoryListView: some View { Group { - Text("Choose your accesory") + Text("Choose your accessory") .foregroundColor(violetColor) .font(.custom("Nunito-Bold", size: 24)) Spacer().frame(height: 50) LazyVGrid(columns: gridItemLayout, spacing: 40) { ForEach($accesoryManager.accesories) { $item in - AccesoryView(item: $item, selectedItem: $accesorySelection) + AccesoryView(item: $item, selectedItem: $accesorySelection, selectedNameItem: $accesoryNameSelection) .onTapGesture { - if let ndx = accesoryManager.accesories.firstIndex(where: { $0.id == accesorySelection }) { - accesoryManager.accesories[ndx].state = false + if userCoins >= item.value { + if let ndx = accesoryManager.accesories.firstIndex(where: { $0.id == accesorySelection }) { + accesoryManager.accesories[ndx].state = false + } + accesorySelection = item.id + accesoryNameSelection = item.name + item.state = true + accesorySelected = item + } else { + accesorySelection = nil + accesorySelected = Accesory(name: "") } - accesorySelection = item.id - item.state = true - accesorySelected = item } } } @@ -110,7 +146,8 @@ struct AvatarSelectionView: View { onboardingSteps: $onboardingSteps, avatarSelection: $avatarSelected, accesorySelection: $accesorySelected, - firstLoad: firstLoad + firstLoad: firstLoad, + accesoryBuy: false ) } label: { Text("Select") @@ -139,8 +176,9 @@ struct AvatarSelectionView: View { } } - init(onboardingSteps: Binding<[OnboardingFlow.Step]>, firstLoad: Bool) { + init(onboardingSteps: Binding<[OnboardingFlow.Step]>, firstLoad: Bool, accesoryLoad: Bool) { self._onboardingSteps = onboardingSteps self.firstLoad = firstLoad + self.accesoryLoad = accesoryLoad } } diff --git a/Balance/Profile/AvatarView.swift b/Balance/Profile/AvatarView.swift index 8bf9855..d699efc 100644 --- a/Balance/Profile/AvatarView.swift +++ b/Balance/Profile/AvatarView.swift @@ -10,14 +10,21 @@ import SwiftUI struct AvatarView: View { @Binding var item: Avatar @Binding var selectedItem: Avatar.ID? - + @Binding var selectedNameItem: String? + var body: some View { ZStack(alignment: .center) { Image(item.name) .resizable(capInsets: EdgeInsets(top: 0.0, leading: 0.0, bottom: 0.0, trailing: 0.0)) .scaledToFit() .accessibilityLabel(item.name) - Image((item.id == selectedItem) ? "checkFill" : "check") +// Image((item.id == selectedItem) ? "checkFill" : "check") +// .resizable() +// .frame(width: 40, height: 40) +// .clipped() +// .offset(x: -50, y: -50) +// .accessibilityLabel("avatarCheck") + Image((item.name == selectedNameItem) ? "checkFill" : "check") .resizable() .frame(width: 40, height: 40) .clipped() diff --git a/Balance/Profile/PasswordResetView.swift b/Balance/Profile/PasswordResetView.swift index 7ba41d9..160b9c0 100644 --- a/Balance/Profile/PasswordResetView.swift +++ b/Balance/Profile/PasswordResetView.swift @@ -7,9 +7,9 @@ import SwiftUI -// swiftlint:disable attributes struct PasswordResetView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss @EnvironmentObject private var authModel: AuthViewModel @State private var alertMessage: String = "" @State private var showingAlert = false @@ -17,37 +17,35 @@ struct PasswordResetView: View { @State var loading = false var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - headerView - Spacer().frame(height: 20) - emailField - Spacer() - saveButton - } - if loading { - ProgressView("Loading...") - .tint(.white) - .accentColor(.white) - .foregroundColor(.white) - .frame(width: 200, height: 200) - .background(Color.black.opacity(0.8)) - .cornerRadius(20, corners: .allCorners) - .ignoresSafeArea() - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + headerView + Spacer().frame(height: 20) + emailField + Spacer() + saveButton } - .disabled(loading) - .onAppear(perform: listen) - .alert(alertMessage, isPresented: $showingAlert) { - Button("OK", role: .cancel) { - authModel.authError = "" - } + if loading { + ProgressView("Loading...") + .tint(.white) + .accentColor(.white) + .foregroundColor(.white) + .frame(width: 200, height: 200) + .background(Color.black.opacity(0.8)) + .cornerRadius(20, corners: .allCorners) + .ignoresSafeArea() + } + } + .disabled(loading) + .onAppear(perform: listen) + .alert(alertMessage, isPresented: $showingAlert) { + Button("OK", role: .cancel) { + authModel.authError = "" } - .navigationTitle("") - .navigationBarTitleDisplayMode(.inline) } + .navigationTitle("") + .navigationBarTitleDisplayMode(.inline) } var headerView: some View { diff --git a/Balance/Profile/PasswordUpdateView.swift b/Balance/Profile/PasswordUpdateView.swift index 90e8d60..50ae478 100644 --- a/Balance/Profile/PasswordUpdateView.swift +++ b/Balance/Profile/PasswordUpdateView.swift @@ -7,9 +7,9 @@ import SwiftUI -// swiftlint:disable attributes struct PasswordUpdateView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss @EnvironmentObject private var authModel: AuthViewModel @State private var alertMessage: String = "" @State private var showingAlert = false @@ -18,37 +18,35 @@ struct PasswordUpdateView: View { @State var loading = false var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Password") - Spacer().frame(height: 40) - titleView - passwordFields - Spacer() - saveButton - } - if loading { - ProgressView("Loading...") - .tint(.white) - .accentColor(.white) - .foregroundColor(.white) - .frame(width: 200, height: 200) - .background(Color.black.opacity(0.8)) - .cornerRadius(20, corners: .allCorners) - .ignoresSafeArea() - } + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Password") + Spacer().frame(height: 40) + titleView + passwordFields + Spacer() + saveButton } - .disabled(loading) - .onAppear(perform: listen) - .onChange(of: authModel.authError) { response in - updateData(value: response) + if loading { + ProgressView("Loading...") + .tint(.white) + .accentColor(.white) + .foregroundColor(.white) + .frame(width: 200, height: 200) + .background(Color.black.opacity(0.8)) + .cornerRadius(20, corners: .allCorners) + .ignoresSafeArea() } - .alert(alertMessage, isPresented: $showingAlert) { - Button("OK", role: .cancel) { - authModel.authError = "" - } + } + .disabled(loading) + .onAppear(perform: listen) + .onChange(of: authModel.authError) { response in + updateData(value: response) + } + .alert(alertMessage, isPresented: $showingAlert) { + Button("OK", role: .cancel) { + authModel.authError = "" } } } diff --git a/Balance/Profile/PersonalDataView.swift b/Balance/Profile/PersonalDataView.swift index 9c5a5d8..52fb829 100644 --- a/Balance/Profile/PersonalDataView.swift +++ b/Balance/Profile/PersonalDataView.swift @@ -10,9 +10,9 @@ import SwiftUI import class FHIR.FHIR import FirebaseAccount -// swiftlint:disable attributes struct PersonalDataView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss @EnvironmentObject var firebaseAccountConfiguration: FirebaseAccountConfiguration @EnvironmentObject var authModel: AuthViewModel @EnvironmentObject var account: Account @@ -27,42 +27,40 @@ struct PersonalDataView: View { @State private var loading = false @State private var deleteButton = false @State private var showingAlert = false - + var body: some View { - ActivityLogContainer { - ZStack { - backgroundColor.edgesIgnoringSafeArea(.all) - VStack { - HeaderMenu(title: "Personal Data") - Spacer().frame(height: 20) - dataView - Spacer() - if deleteButton { - removeButton - } - } - if loading { - ProgressView("Loading...") - .tint(.white) - .accentColor(.white) - .foregroundColor(.white) - .frame(width: 200, height: 200) - .background(Color.black.opacity(0.8)) - .cornerRadius(20, corners: .allCorners) - .ignoresSafeArea() + ZStack { + backgroundColor.edgesIgnoringSafeArea(.all) + VStack { + HeaderMenu(title: "Personal Data") + Spacer().frame(height: 20) + dataView + Spacer() + if deleteButton { + removeButton } } - .onAppear { - cleanDataView() + if loading { + ProgressView("Loading...") + .tint(.white) + .accentColor(.white) + .foregroundColor(.white) + .frame(width: 200, height: 200) + .background(Color.black.opacity(0.8)) + .cornerRadius(20, corners: .allCorners) + .ignoresSafeArea() } - .onShake { - print("Device shaken!") - self.deleteButton = true - } - .alert(alertMessage, isPresented: $showingAlert) { - Button("OK", role: .cancel) { - authModel.authError = "" - } + } + .onAppear { + cleanDataView() + } + .onShake { + print("Device shaken!") + self.deleteButton = true + } + .alert(alertMessage, isPresented: $showingAlert) { + Button("OK", role: .cancel) { + authModel.authError = "" } } } @@ -192,6 +190,7 @@ struct PersonalDataView: View { self.deleteButton = false } } + struct PersonalDataView_Previews: PreviewProvider { static var previews: some View { PersonalDataView() diff --git a/Balance/Profile/ProfileCellView.swift b/Balance/Profile/ProfileCellView.swift index 8dc90ef..f506df0 100644 --- a/Balance/Profile/ProfileCellView.swift +++ b/Balance/Profile/ProfileCellView.swift @@ -12,19 +12,17 @@ struct ProfileCellView: View { var text: String var body: some View { - ActivityLogContainer { - HStack { - iconView - textView - } - .frame(maxWidth: 300) - .frame(height: 60) - .foregroundColor(darkBlueColor) - .background(RoundedRectangle(cornerRadius: 20).fill(.white)) - .clipped() - .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) - .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) + HStack { + iconView + textView } + .frame(maxWidth: 300) + .frame(height: 60) + .foregroundColor(darkBlueColor) + .background(RoundedRectangle(cornerRadius: 20).fill(.white)) + .clipped() + .shadow(color: Color.black.opacity(0.10), radius: 7, x: 2, y: 2) + .padding(EdgeInsets(top: 0, leading: 24, bottom: 0, trailing: 24)) } var textView: some View { diff --git a/Balance/Profile/ProfileView.swift b/Balance/Profile/ProfileView.swift index 2b2b122..8da3a14 100644 --- a/Balance/Profile/ProfileView.swift +++ b/Balance/Profile/ProfileView.swift @@ -11,9 +11,9 @@ import class FHIR.FHIR import SwiftUI // swiftlint:disable type_body_length -// swiftlint:disable attributes struct ProfileView: View { - @Environment(\.dismiss) private var dismiss + @Environment(\.dismiss) + private var dismiss @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false @SceneStorage(StorageKeys.onboardingFlowStep) @@ -25,6 +25,7 @@ struct ProfileView: View { @EnvironmentObject var noteStore: NoteStore @EnvironmentObject var drawStore: DrawStore @EnvironmentObject var coloringStore: ColoringStore + @EnvironmentObject var activityLogEntry: ActivityLogEntry #if DEMO @EnvironmentObject var logStore: ActivityLogStore #endif @@ -33,41 +34,41 @@ struct ProfileView: View { @State private var email = "" @State private var patientID = "" @State private var showAlert = false + @State private var logs = [ActivityLogEntry]() + @State private var logsIsEmpty = true var body: some View { - ActivityLogContainer { - ZStack { - VStack(alignment: .center, spacing: 0) { - HeaderMenu(title: "") - .background(primaryColor) - avatarChangeView - userData - cellsView - Spacer() - } + ZStack { + VStack(alignment: .center, spacing: 0) { + HeaderMenu(title: "") + .background(primaryColor) + avatarChangeView + userData + cellsView + Spacer() } - .onAppear { + } + .onAppear { #if DEMO - loadUserLocal() - loadLogs() + loadUserLocal() + loadLogs() #else - loadUser() + loadUser() #endif + } + .onReceive(account.objectWillChange) { + if account.signedIn { + completedOnboardingFlow = true + } else { + completedOnboardingFlow = false } - .onReceive(account.objectWillChange) { - if account.signedIn { - completedOnboardingFlow = true - } else { - completedOnboardingFlow = false - } - } - .onChange(of: authModel.profile) { profile in - withAnimation(.easeInOut(duration: 1.0)) { - self.displayName = profile?.displayName ?? "" - self.email = profile?.email ?? "" - self.patientID = profile?.id ?? "0000" - self.avatar = profile?.avatar ?? "" - } + } + .onChange(of: authModel.profile) { profile in + withAnimation(.easeInOut(duration: 1.0)) { + self.displayName = profile?.displayName ?? "" + self.email = profile?.email ?? "" + self.patientID = profile?.id ?? "0000" + self.avatar = profile?.avatar ?? "" } } } @@ -98,8 +99,10 @@ struct ProfileView: View { updateOption #else resetOption - shareOption - shareLink + if logsIsEmpty == false { + shareOption + shareLink + } #endif logoutOption } @@ -115,24 +118,32 @@ struct ProfileView: View { }) { profileView }.sheet(isPresented: $showingAvatarSheet) { - AvatarSelectionView(onboardingSteps: $onboardingSteps, firstLoad: false).environmentObject(authModel) + AvatarSelectionView(onboardingSteps: $onboardingSteps, firstLoad: false, accesoryLoad: false).environmentObject(authModel) } } var resetOption: some View { Button { - UserImageCache.remove(key: self.patientID.appending("UploadedArray")) - UserImageCache.remove(key: self.patientID.appending("RemovedArray")) - UserImageCache.remove(key: self.patientID.appending("FavoritesArray")) - logStore.removeStore() - noteStore.removeStore() - drawStore.removeStore() - coloringStore.removeStore() showAlert = true } label: { ProfileCellView(image: "info", text: "Reset user") - }.alert("Reset", isPresented: $showAlert) { - Button("Done", role: .cancel) { } + }.confirmationDialog("Reset User", isPresented: $showAlert) { + Button("Canel", role: .cancel) { + showAlert = false + } + Button("Reset") { + activityLogEntry.reset() + // NotificationCenter.default.post(name: Notification.Name.goBackground, object: nil) + self.logs.removeAll() + logsIsEmpty = true + UserImageCache.remove(key: self.patientID.appending("UploadedArray")) + UserImageCache.remove(key: self.patientID.appending("RemovedArray")) + UserImageCache.remove(key: self.patientID.appending("FavoritesArray")) + logStore.removeStore() + noteStore.removeStore() + drawStore.removeStore() + coloringStore.removeStore() + } } } @@ -301,32 +312,38 @@ struct ProfileView: View { case .failure(let error): print(error.localizedDescription) case .success(let logs): - logStore.logs = logs + self.logs = logs + if self.logs.isEmpty { + logsIsEmpty = true + } else { + logsIsEmpty = false + } } } } func convertToCSV() -> URL { var logActions = [LogAction]() - - var noteAsCSV = "id, activeStartTime, activeEndTime, activeDuration, actionTime, actionDescription\n" - for log in logStore.logs { + var noteAsCSV = "sessionID, sessionStartTime, sessionEndTime, sessionDuration, description, startTime, endTime, duration\n" + for log in logs { for action in log.actions { logActions.append( LogAction( - id: log.id, - startTime: log.startTime, - endTime: log.endTime, - duration: log.duration, - actionTime: action.time, - actionDesc: action.description + sessionID: log.id, + sessionStartTime: log.startTime, + sessionEndTime: log.endTime, + sessionDuration: log.duration, + description: action.description, + startTime: action.startTime, + endTime: action.endTime, + duration: action.duration ) ) } } - for action in logActions.sorted(by: { $0.actionTime.compare($1.actionTime) == .orderedAscending }) { - noteAsCSV.append(contentsOf: "\"\(action.id)\",\"\(action.startTime)\",\"\(action.endTime)\",\"\(action.duration)\",\"\(action.actionTime)\",\"\(action.actionDesc)\"\n") + for action in logActions.sorted(by: { $0.startTime.compare($1.startTime) == .orderedAscending }) { + noteAsCSV.append(contentsOf: "\"\(action.sessionID)\",\"\(DateFormatter.sharedDateFormatter.string(from: action.sessionStartTime))\",\"\(DateFormatter.sharedDateFormatter.string(from: action.sessionEndTime))\",\"\(action.sessionDuration)\",\"\(action.description)\",\"\(DateFormatter.sharedDateFormatter.string(from: action.startTime))\",\"\(DateFormatter.sharedDateFormatter.string(from: action.endTime))\",\"\(action.duration)\"\n") } let fileManager = FileManager.default @@ -344,29 +361,29 @@ struct ProfileView: View { func convertToPlainText() -> String { var noteAsCSV = "ParticipantID: " + self.patientID + "\n" - noteAsCSV.append(contentsOf: "id, activeStartTime, activeEndTime, activeDuration, actionTime, actionDescription\n") + noteAsCSV.append(contentsOf: "sessionID, sessionStartTime, sessionEndTime, sessionDuration, description, startTime, endTime, duration\n") var logActions = [LogAction]() - - for log in logStore.logs { + for log in logs { for action in log.actions { logActions.append( LogAction( - id: log.id, - startTime: log.startTime, - endTime: log.endTime, - duration: log.duration, - actionTime: action.time, - actionDesc: action.description + sessionID: log.id, + sessionStartTime: log.startTime, + sessionEndTime: log.endTime, + sessionDuration: log.duration, + description: action.description, + startTime: action.startTime, + endTime: action.endTime, + duration: action.duration ) ) } } - for action in logActions.sorted(by: { $0.actionTime.compare($1.actionTime) == .orderedAscending }) { - noteAsCSV.append(contentsOf: "\"\(action.id)\",\"\(action.startTime)\",\"\(action.endTime)\",\"\(action.duration)\",\"\(action.actionTime)\",\"\(action.actionDesc)\"\n") + for action in logActions.sorted(by: { $0.startTime.compare($1.startTime) == .orderedAscending }) { + noteAsCSV.append(contentsOf: "\"\(action.sessionID)\",\"\(DateFormatter.sharedDateFormatter.string(from: action.sessionStartTime))\",\"\(DateFormatter.sharedDateFormatter.string(from: action.sessionEndTime))\",\"\(action.sessionDuration)\",\"\(action.description)\",\"\(DateFormatter.sharedDateFormatter.string(from: action.startTime))\",\"\(DateFormatter.sharedDateFormatter.string(from: action.endTime))\",\"\(action.duration)\"\n") } - return noteAsCSV } } diff --git a/Balance/SOS/SOSView.swift b/Balance/SOS/SOSView.swift index 9ef179b..8c61227 100644 --- a/Balance/SOS/SOSView.swift +++ b/Balance/SOS/SOSView.swift @@ -8,45 +8,43 @@ import SwiftUI -// swiftlint:disable attributes struct SOSView: View { - @Environment(\.dismiss) var dismiss + @Environment(\.dismiss) + var dismiss var clipsToBounds = false var body: some View { - ActivityLogContainer { - VStack(spacing: 20) { - Spacer() - Image("Diary") - .resizable() - .scaledToFit() - .frame(width: 100.0, height: 100.0) - .accessibilityLabel("Diary") - textView - ScrollView { - SOSCellView( - title: "Body sensations", - subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." - ) - SOSCellView( - title: "Guided meditation", - subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." - ) - SOSCellView( - title: "Distraction", - subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." - ) - SOSCellView( - title: "Deep breating", - subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." - ) - SOSCellView( - title: "Sensorial activity", - subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." - ) - } - saveButton + VStack(spacing: 20) { + Spacer() + Image("Diary") + .resizable() + .scaledToFit() + .frame(width: 100.0, height: 100.0) + .accessibilityLabel("Diary") + textView + ScrollView { + SOSCellView( + title: "Body sensations", + subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." + ) + SOSCellView( + title: "Guided meditation", + subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." + ) + SOSCellView( + title: "Distraction", + subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." + ) + SOSCellView( + title: "Deep breating", + subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." + ) + SOSCellView( + title: "Sensorial activity", + subtitle: "lrem ipsum dolor sit amet consecte tuer adipiscing..." + ) } + saveButton }.background(backgroundColor) } diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_10.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_10.imageset/Contents.json new file mode 100644 index 0000000..52e084a --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_10.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_10.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_10.imageset/acc_10.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_10.imageset/acc_10.svg new file mode 100644 index 0000000..e32f85c --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_10.imageset/acc_10.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_11.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_11.imageset/Contents.json new file mode 100644 index 0000000..646108a --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_11.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_11.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_11.imageset/acc_11.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_11.imageset/acc_11.svg new file mode 100644 index 0000000..ff33e26 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_11.imageset/acc_11.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_12.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_12.imageset/Contents.json new file mode 100644 index 0000000..468ae81 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_12.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_12.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_12.imageset/acc_12.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_12.imageset/acc_12.svg new file mode 100644 index 0000000..61616a4 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_12.imageset/acc_12.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_13.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_13.imageset/Contents.json new file mode 100644 index 0000000..94be3bc --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_13.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_13.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_13.imageset/acc_13.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_13.imageset/acc_13.svg new file mode 100644 index 0000000..cbaa3da --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_13.imageset/acc_13.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_14.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_14.imageset/Contents.json new file mode 100644 index 0000000..5813c80 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_14.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_14.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_14.imageset/acc_14.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_14.imageset/acc_14.svg new file mode 100644 index 0000000..f5c971b --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_14.imageset/acc_14.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_15.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_15.imageset/Contents.json new file mode 100644 index 0000000..b121e4b --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_15.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_15.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_15.imageset/acc_15.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_15.imageset/acc_15.svg new file mode 100644 index 0000000..1ceda92 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_15.imageset/acc_15.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_16.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_16.imageset/Contents.json new file mode 100644 index 0000000..7dda554 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_16.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_16.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_16.imageset/acc_16.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_16.imageset/acc_16.svg new file mode 100644 index 0000000..48f3714 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_16.imageset/acc_16.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_17.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_17.imageset/Contents.json new file mode 100644 index 0000000..a00198a --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_17.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_17.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_17.imageset/acc_17.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_17.imageset/acc_17.svg new file mode 100644 index 0000000..69c80ef --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_17.imageset/acc_17.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_18.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_18.imageset/Contents.json new file mode 100644 index 0000000..bbbc510 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_18.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_18.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_18.imageset/acc_18.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_18.imageset/acc_18.svg new file mode 100644 index 0000000..e384137 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_18.imageset/acc_18.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_19.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_19.imageset/Contents.json new file mode 100644 index 0000000..b6c434f --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_19.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_19.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_19.imageset/acc_19.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_19.imageset/acc_19.svg new file mode 100644 index 0000000..af5b8b6 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_19.imageset/acc_19.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_20.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_20.imageset/Contents.json new file mode 100644 index 0000000..7db0027 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_20.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_20.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_20.imageset/acc_20.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_20.imageset/acc_20.svg new file mode 100644 index 0000000..d75992d --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_20.imageset/acc_20.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_21.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_21.imageset/Contents.json new file mode 100644 index 0000000..4637529 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_21.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_21.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_21.imageset/acc_21.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_21.imageset/acc_21.svg new file mode 100644 index 0000000..c276c24 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_21.imageset/acc_21.svg @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_5.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_5.imageset/Contents.json new file mode 100644 index 0000000..26e74a2 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_5.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_5.imageset/acc_5.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_5.imageset/acc_5.svg new file mode 100644 index 0000000..df6d2d9 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_5.imageset/acc_5.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_6.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_6.imageset/Contents.json new file mode 100644 index 0000000..d7c61b9 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_6.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_6.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_6.imageset/acc_6.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_6.imageset/acc_6.svg new file mode 100644 index 0000000..284a659 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_6.imageset/acc_6.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_7.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_7.imageset/Contents.json new file mode 100644 index 0000000..95a44aa --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_7.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_7.imageset/acc_7.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_7.imageset/acc_7.svg new file mode 100644 index 0000000..452b43e --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_7.imageset/acc_7.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_8.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_8.imageset/Contents.json new file mode 100644 index 0000000..cf28919 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_8.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_8.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_8.imageset/acc_8.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_8.imageset/acc_8.svg new file mode 100644 index 0000000..ffcad9c --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_8.imageset/acc_8.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_9.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_9.imageset/Contents.json new file mode 100644 index 0000000..092b4f4 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_9.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "acc_9.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_9.imageset/acc_9.svg b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_9.imageset/acc_9.svg new file mode 100644 index 0000000..3868414 --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/ACCESORIOS/acc_9.imageset/acc_9.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Balance/Supporting Files/Assets.xcassets/lock.imageset/Contents.json b/Balance/Supporting Files/Assets.xcassets/lock.imageset/Contents.json new file mode 100644 index 0000000..8ca48af --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/lock.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "lock.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Balance/Supporting Files/Assets.xcassets/lock.imageset/lock.svg b/Balance/Supporting Files/Assets.xcassets/lock.imageset/lock.svg new file mode 100644 index 0000000..c65abba --- /dev/null +++ b/Balance/Supporting Files/Assets.xcassets/lock.imageset/lock.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Balance/Utils/BalanceExtensions.swift b/Balance/Utils/BalanceExtensions.swift index a35c9e7..4c7973f 100644 --- a/Balance/Utils/BalanceExtensions.swift +++ b/Balance/Utils/BalanceExtensions.swift @@ -125,3 +125,30 @@ extension UIApplication { return aux } } + +extension Notification.Name { + static let goBackground = Notification.Name("goBackground") + static let coinsUpdate = Notification.Name("coinsUpdate") + static let coinsRefresh = Notification.Name("coinsRefresh") + static let coinsAlert = Notification.Name("coinsAlert") +} + +// swiftlint:disable operator_whitespace +// swiftlint:disable large_tuple +extension Date { + static func -(recent: Date, previous: Date) -> (hour: Int?, minute: Int?, second: Int?) { + let hour = Calendar.current.dateComponents([.hour], from: previous, to: recent).hour + let minute = Calendar.current.dateComponents([.minute], from: previous, to: recent).minute + let second = Calendar.current.dateComponents([.second], from: previous, to: recent).second + + return (hour: hour, minute: minute, second: second) + } +} + +extension DateFormatter { + static var sharedDateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + return dateFormatter + }() +} diff --git a/Balance/Utils/BalanceSharedContext/StorageKeys.swift b/Balance/Utils/BalanceSharedContext/StorageKeys.swift index 4369a58..be9c484 100644 --- a/Balance/Utils/BalanceSharedContext/StorageKeys.swift +++ b/Balance/Utils/BalanceSharedContext/StorageKeys.swift @@ -14,7 +14,8 @@ public enum StorageKeys { /// A `Step` flag indicating the current step in the onboarding process. public static let onboardingFlowStep = "onboardingFlow.step" - + /// A `spotifyConnect` flag indicating the current step in the onboarding process. + public static let spotifyConnect = "spotifyConnect" // MARK: - Home /// The currently selected home tab. public static let homeTabSelection = "home.tabselection" diff --git a/Balance/Utils/Constant.swift b/Balance/Utils/Constant.swift index 5bd068a..ca359cb 100644 --- a/Balance/Utils/Constant.swift +++ b/Balance/Utils/Constant.swift @@ -57,7 +57,7 @@ let balHeight = UIScreen.main.bounds.height let notch = 50.0 let primaryColor = Color(#colorLiteral(red: Float(0.30), green: Float(0.79), blue: Float(0.94), alpha: Float(1.00))) -let navigationBarHeightHome = 120.0 +let navigationBarHeightHome = 130.0 let navigationBarHeight = 90.0 let darkBlueColor = Color(red: 0.25, green: 0.38, blue: 0.50, opacity: 1.00) let backgroundColor = Color(#colorLiteral(red: 0.9882352941, green: 0.9882352941, blue: 0.9882352941, alpha: 1)) @@ -74,3 +74,6 @@ let silentTrack = "spotify:track:7p5bQJB4XsZJEEn6Tb7EaL" let cantAnswer = 10 let spotifyURL = "https://itunes.com/apps/spotifyltd" + +let coinsValue = 5 +let coinsTime = 15 diff --git a/Balance/Utils/GlobalBannerContent.swift b/Balance/Utils/GlobalBannerContent.swift new file mode 100644 index 0000000..b57f14f --- /dev/null +++ b/Balance/Utils/GlobalBannerContent.swift @@ -0,0 +1,48 @@ +// +// DemoGlobalBannerContent.swift +// Balance +// +// Created by Gonzalo Perisset on 08/08/2023. +// + +import SwiftUI + +struct GlobalBannerContent: View { + @ObservedObject var bannerManager: PresentBannerManager + + var body: some View { + ZStack { + HStack { + Image(systemName: "star.circle") + VStack(alignment: .leading, spacing: 2) { + Text(bannerManager.banner?.title ?? "") + .bold() + Text(bannerManager.banner?.message ?? "") + .fontWeight(.medium) + } + Spacer() + } + .padding(12) + .foregroundColor(.white) + .background(Color.gray) + .cornerRadius(8) + + Spacer() + } + .padding() + .animation(.easeInOut) + .transition(AnyTransition.move(edge: .top).combined(with: .opacity)) + .onTapGesture { + withAnimation { + bannerManager.dismiss() + } + } + .onAppear(perform: { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + withAnimation { + bannerManager.dismiss() + } + } + }) + } +} diff --git a/Balance/Utils/NavigationUtil.swift b/Balance/Utils/NavigationUtil.swift index b75dc7a..ff7a22a 100644 --- a/Balance/Utils/NavigationUtil.swift +++ b/Balance/Utils/NavigationUtil.swift @@ -7,25 +7,48 @@ import SwiftUI +// swiftlint:disable all enum NavigationUtil { - static func popToRootView() { - findNavigationController(viewController: UIApplication.shared.currentUIWindow()?.rootViewController)? - .popToRootViewController(animated: true) - } - - static func findNavigationController(viewController: UIViewController?) -> UINavigationController? { - guard let viewController = viewController else { - return nil + static func dismiss(_ n: Int) { + let rootViewController = UIApplication.shared.connectedScenes + .filter { $0.activationState == .foregroundActive } + .map {$0 as? UIWindowScene } + .compactMap { $0 } + .first?.windows + .filter({ $0.isKeyWindow }).first?.rootViewController + guard let rootViewController = rootViewController else { return } + + var leafFlound = false + var viewStack: [UIViewController] = [rootViewController] + while(!leafFlound) { + if let presentedViewController = viewStack.last?.presentedViewController { + viewStack.append(presentedViewController) + } else { + leafFlound = true + } + } + let presentingViewController = viewStack[max(0, viewStack.count - n - 1)] + presentingViewController.dismiss(animated: true) } - - if let navigationController = viewController as? UINavigationController { - return navigationController + + static func popToRootView() { + findNavigationController(viewController: UIApplication.shared.currentUIWindow()?.rootViewController)? + .popToRootViewController(animated: true) } - - for childViewController in viewController.children { - return findNavigationController(viewController: childViewController) + + static func findNavigationController(viewController: UIViewController?) -> UINavigationController? { + guard let viewController = viewController else { + return nil + } + + if let navigationController = viewController as? UINavigationController { + return navigationController + } + + for childViewController in viewController.children { + return findNavigationController(viewController: childViewController) + } + + return nil } - - return nil - } } diff --git a/Balance/Utils/PresentBannerManager.swift b/Balance/Utils/PresentBannerManager.swift new file mode 100644 index 0000000..c8ae43b --- /dev/null +++ b/Balance/Utils/PresentBannerManager.swift @@ -0,0 +1,29 @@ +// +// PresentBannerManager.swift +// Balance +// +// Created by Gonzalo Perisset on 08/08/2023. +// + +import SwiftUI + +struct DemoBanner { + let title: String + let message: String +} + +final class PresentBannerManager: ObservableObject { + @Published var isPresented = false + + var banner: DemoBanner? { + didSet { + isPresented = banner != nil + } + } + + func dismiss() { + if isPresented { + isPresented = false + } + } +}