Skip to content

Commit

Permalink
Feature/bal 165 gp coins exchange (#168)
Browse files Browse the repository at this point in the history
- Data export
- Coins exchange
- Accessory View
-----------------------
Please remove old app and and install this version. 
All data will be lost.
-----------------------
  • Loading branch information
gperissetcelteeka authored Aug 8, 2023
1 parent 1aa591d commit 24dec19
Show file tree
Hide file tree
Showing 103 changed files with 2,188 additions and 1,053 deletions.
12 changes: 12 additions & 0 deletions Balance.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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 */; };
Expand Down Expand Up @@ -245,6 +248,7 @@
6C39EA2029C9EA610095573E /* SOSView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SOSView.swift; sourceTree = "<group>"; };
6C3BB1F22A151D1F008FEB93 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
6C3BB1F42A1646C5008FEB93 /* PasswordResetView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordResetView.swift; sourceTree = "<group>"; };
6C3D39962A812D0F00864CC0 /* AccesoryArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccesoryArray.swift; sourceTree = "<group>"; };
6C3DD6E32A126DAF00456646 /* GuessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessView.swift; sourceTree = "<group>"; };
6C3DD6E52A12742D00456646 /* BoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxView.swift; sourceTree = "<group>"; };
6C4676CA2A031C1200777421 /* NewTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTimerView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -282,6 +286,8 @@
6C58B24F29F6B673000FE8DD /* DrawHighlightView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawHighlightView.swift; sourceTree = "<group>"; };
6C58B25129F7293A000FE8DD /* NavigationUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationUtil.swift; sourceTree = "<group>"; };
6C60EFA02A16548F00A01862 /* ShakeGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShakeGesture.swift; sourceTree = "<group>"; };
6C738BDC2A82795F009B359E /* PresentBannerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentBannerManager.swift; sourceTree = "<group>"; };
6C738BDE2A827B67009B359E /* GlobalBannerContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalBannerContent.swift; sourceTree = "<group>"; };
6C80C00829CCF8FA003DD5B9 /* Nunito-SemiBoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-SemiBoldItalic.ttf"; sourceTree = "<group>"; };
6C80C00929CCF8FB003DD5B9 /* Nunito-BlackItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-BlackItalic.ttf"; sourceTree = "<group>"; };
6C80C00A29CCF8FD003DD5B9 /* Nunito-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-MediumItalic.ttf"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -706,6 +713,8 @@
6C3BB1F22A151D1F008FEB93 /* SearchBar.swift */,
6C60EFA02A16548F00A01862 /* ShakeGesture.swift */,
6C92E3C12A17C84E003FE239 /* RoundedCorner.swift */,
6C738BDC2A82795F009B359E /* PresentBannerManager.swift */,
6C738BDE2A827B67009B359E /* GlobalBannerContent.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand All @@ -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 */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/firebase-ios-sdk.git",
"state" : {
"revision" : "e700a8f40c87c31cab7984875fcc1225d96b25bf",
"version" : "10.11.0"
"revision" : "5034479ca0c4f32f299677fb0ba1fe4d3e3e20b4",
"version" : "10.10.0"
}
},
{
"identity" : "googleappmeasurement",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleAppMeasurement.git",
"state" : {
"revision" : "62e3a0c09a75e2637f5300d46f05a59313f1c286",
"version" : "10.11.0"
"revision" : "69f5b8425dd473d2f2475bba7f88f82cd9da0e36",
"version" : "10.10.0"
}
},
{
Expand Down
10 changes: 4 additions & 6 deletions Balance/ActivityLogging/ActivityLogBaseView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SwiftUI

// swiftlint:disable lower_acl_than_parent
struct ActivityLogContainer<Content>: View where Content: View {
@StateObject var activityLogEntry = ActivityLogEntry()
@EnvironmentObject var activityLogEntry: ActivityLogEntry
private let content: Content

var body: some View {
Expand All @@ -31,6 +31,9 @@ struct ActivityLogBaseView<Content>: 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
Expand All @@ -43,11 +46,6 @@ struct ActivityLogBaseView<Content>: 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
Expand Down
28 changes: 18 additions & 10 deletions Balance/ActivityLogging/ActivityLogStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ 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,
in: .userDomainMask,
appropriateFor: nil,
create: false
)
.appendingPathComponent("activityLog.data")
.appendingPathComponent("\(UserDefaults.standard.string(forKey: "lastPatient") ?? "")_activityLog.data")
}

static func load(completion: @escaping (Result<[ActivityLogEntry], Error>) -> Void) {
Expand Down Expand Up @@ -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)
}
}
}
}
}
}
103 changes: 74 additions & 29 deletions Balance/ActivityLogging/ActivityStorageManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand All @@ -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"))
Expand Down
29 changes: 28 additions & 1 deletion Balance/Balance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import CardinalKit
import SwiftUI

// swiftlint:disable closure_body_length
@main
struct Balance: App {
@UIApplicationDelegateAdaptor(BalanceAppDelegate.self)
Expand All @@ -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 {
Expand All @@ -32,6 +37,9 @@ struct Balance: App {
} else {
OnboardingFlow()
}
if bannerManager.isPresented {
GlobalBannerContent(bannerManager: bannerManager)
}
}
.testingSetup()
.cardinalKit(appDelegate)
Expand All @@ -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")
}
}
}
}
}
Loading

0 comments on commit 24dec19

Please sign in to comment.