Skip to content

Commit 750ab5c

Browse files
feat: restore user data (#61)
1 parent 8a167f2 commit 750ab5c

File tree

12 files changed

+286
-52
lines changed

12 files changed

+286
-52
lines changed

GoMoney.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
083EA336290659660079605F /* TransactionTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083EA335290659660079605F /* TransactionTag.swift */; };
4040
083EA339290676EB0079605F /* StatViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083EA338290676EB0079605F /* StatViewModel.swift */; };
4141
083EA33B2906933A0079605F /* StatLineChartCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083EA33A2906933A0079605F /* StatLineChartCell.swift */; };
42+
083EDBAE292A3ED50058F5D7 /* GMAuthViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083EDBAD292A3ED40058F5D7 /* GMAuthViewController.swift */; };
4243
085F7526291215B80094A026 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085F7525291215B80094A026 /* SettingsViewController.swift */; };
4344
085F752A2912490E0094A026 /* SettingsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085F75292912490E0094A026 /* SettingsTableViewCell.swift */; };
4445
085F752C29124CEC0094A026 /* BlockerToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085F752B29124CEC0094A026 /* BlockerToggle.swift */; };
@@ -203,6 +204,7 @@
203204
083EA335290659660079605F /* TransactionTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionTag.swift; sourceTree = "<group>"; };
204205
083EA338290676EB0079605F /* StatViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatViewModel.swift; sourceTree = "<group>"; };
205206
083EA33A2906933A0079605F /* StatLineChartCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatLineChartCell.swift; sourceTree = "<group>"; };
207+
083EDBAD292A3ED40058F5D7 /* GMAuthViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GMAuthViewController.swift; sourceTree = "<group>"; };
206208
085F7525291215B80094A026 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
207209
085F75292912490E0094A026 /* SettingsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTableViewCell.swift; sourceTree = "<group>"; };
208210
085F752B29124CEC0094A026 /* BlockerToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockerToggle.swift; sourceTree = "<group>"; };
@@ -703,6 +705,7 @@
703705
08DB56E528F8FC7D00170C60 /* View */,
704706
08C8731728F865B200DC859D /* SignUp */,
705707
08C872EC28F6C5DE00DC859D /* SignIn */,
708+
083EDBAD292A3ED40058F5D7 /* GMAuthViewController.swift */,
706709
);
707710
path = Auth;
708711
sourceTree = "<group>";
@@ -1128,6 +1131,7 @@
11281131
083EA339290676EB0079605F /* StatViewModel.swift in Sources */,
11291132
082BF96828FD1D510094FE94 /* Podfile in Sources */,
11301133
088D691C29015865003D0660 /* AddExpenseField.swift in Sources */,
1134+
083EDBAE292A3ED50058F5D7 /* GMAuthViewController.swift in Sources */,
11311135
08F0688D2921DBEE005C58EC /* ExchangeCell.swift in Sources */,
11321136
083B14DF2914EF300058E36E /* SyncManager.swift in Sources */,
11331137
08C6894D2913B01C002071CC /* TrackingService.swift in Sources */,

GoMoney/Models/Expense.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,15 @@ struct DateAmount {
8787
let date: Date
8888
var totalAmount: Double
8989
}
90+
91+
/// Transaction structure on firestore.
92+
struct RemoteTransaction: Codable {
93+
var _id: String
94+
var type: String
95+
var tag: String
96+
var amount: Double
97+
var note: String
98+
var occuredOn: Date
99+
var createdAt: Date?
100+
var updatedAt: Date?
101+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import UIKit
2+
3+
class GMAuthViewController: GMViewController {
4+
func initData(completion: @escaping (String?) -> Void) {
5+
GMLoadingView.shared.startLoadingAnimation(with: "Initing data ...")
6+
TagService.shared.createDefaultDb { err in
7+
GMLoadingView.shared.endLoadingAnimation()
8+
if let err = err {
9+
completion(err.localizedDescription)
10+
} else {
11+
completion(nil)
12+
}
13+
}
14+
}
15+
16+
func initDataAndGoHome() {
17+
initData { [weak self] err in
18+
if let err = err {
19+
self?.errorAlert(message: err)
20+
} else {
21+
self?.navigateToMainVC()
22+
}
23+
}
24+
}
25+
26+
func navigateToMainVC() {
27+
let homeVC = GMTabBarViewController()
28+
if let delegate = view.window?.windowScene?.delegate as? SceneDelegate {
29+
if let window = delegate.window {
30+
window.rootViewController = homeVC
31+
32+
let options: UIView.AnimationOptions = .transitionCrossDissolve
33+
let duration: TimeInterval = 0.5
34+
UIView.transition(
35+
with: window,
36+
duration: duration,
37+
options: options,
38+
animations: {},
39+
completion: { _ in })
40+
}
41+
}
42+
}
43+
44+
func restoreData(completion: @escaping (Error?) -> Void) {
45+
GMLoadingView.shared.startLoadingAnimation(with: "Restoring data ...")
46+
AuthService.shared.restoreUserData(completion: { err in
47+
GMLoadingView.shared.endLoadingAnimation()
48+
completion(err)
49+
})
50+
}
51+
52+
func restoreDataAndGoHome() {
53+
restoreData { [weak self] err in
54+
if let err = err {
55+
self?.errorAlert(message: err.localizedDescription)
56+
} else {
57+
self?.navigateToMainVC()
58+
}
59+
}
60+
}
61+
62+
func checkIfNewUser(completion: @escaping (Bool) -> Void) {
63+
RemoteService.shared.checkIfUserExist { result in
64+
switch result {
65+
case .success(let exist):
66+
completion(!exist)
67+
case .failure(let err):
68+
self.errorAlert(message: err.localizedDescription)
69+
}
70+
}
71+
}
72+
}

GoMoney/Scences/Auth/SignIn/SignInPasswordVC.swift

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import UIKit
22

3-
class SignInPasswordVC: GMViewController {
3+
class SignInPasswordVC: GMAuthViewController {
44
// MARK: - Content
55

66
private enum Content {
@@ -116,25 +116,18 @@ class SignInPasswordVC: GMViewController {
116116
errorLabel.text = error
117117
} else {
118118
errorLabel.text = ""
119-
GMLoadingView.shared.startLoadingAnimation()
119+
GMLoadingView.shared.startLoadingAnimation(with: "Logging in ...")
120120
viewModel.signInWithEmailAndPassword(email: email, password: password) { [weak self] error in
121-
GMLoadingView.shared.endLoadingAnimation()
122121
if error != nil {
122+
GMLoadingView.shared.endLoadingAnimation()
123123
self?.errorLabel.text = error?.localizedDescription
124124
} else {
125-
self?.onSuccessLogin()
125+
self?.restoreDataAndGoHome()
126126
}
127127
}
128128
}
129129
}
130130
}
131-
132-
private func navigateToMainVC() {
133-
let homeVC = GMTabBarViewController()
134-
if let delegate = view.window?.windowScene?.delegate as? SceneDelegate {
135-
delegate.window?.rootViewController = homeVC
136-
}
137-
}
138131
}
139132

140133
extension SignInPasswordVC: UITextFieldDelegate {

GoMoney/Scences/Auth/SignIn/SignInViewController.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import UIKit
99

10-
class SignInViewController: GMViewController {
10+
class SignInViewController: GMAuthViewController {
1111
private lazy var img: UIImageView = .build { view in
1212
view.image = UIImage(named: "onboard_1")
1313
}
@@ -108,18 +108,18 @@ class SignInViewController: GMViewController {
108108
with: self,
109109
completion: { [weak self] err in
110110
if let err = err {
111+
GMLoadingView.shared.endLoadingAnimation()
111112
self?.errorAlert(message: err)
112113
} else {
113-
self?.navigateToMainVC()
114+
self?.checkIfNewUser { isNew in
115+
if isNew {
116+
self?.initDataAndGoHome()
117+
} else {
118+
self?.restoreDataAndGoHome()
119+
}
120+
}
114121
}
115122
}
116123
)
117124
}
118-
119-
private func navigateToMainVC() {
120-
let homeVC = GMTabBarViewController()
121-
if let delegate = view.window?.windowScene?.delegate as? SceneDelegate {
122-
delegate.window?.rootViewController = homeVC
123-
}
124-
}
125125
}

GoMoney/Scences/Auth/SignUp/SignUpPasswordVC.swift

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import UIKit
22

3-
class SignUpPasswordVC: GMViewController {
3+
class SignUpPasswordVC: GMAuthViewController {
44
private enum Constant {
55
static let padding: CGFloat = 16
66
}
@@ -121,7 +121,7 @@ class SignUpPasswordVC: GMViewController {
121121
self?.errorLabel.text = error?.localizedDescription
122122
} else {
123123
// TODO: navigateToDetailVC
124-
self?.navigateToMainVC()
124+
self?.initDataAndGoHome()
125125
}
126126
}
127127
}
@@ -133,13 +133,6 @@ class SignUpPasswordVC: GMViewController {
133133
errorLabel.text = ""
134134
}
135135

136-
private func navigateToMainVC() {
137-
let homeVC = GMTabBarViewController()
138-
if let delegate = view.window?.windowScene?.delegate as? SceneDelegate {
139-
delegate.window?.rootViewController = homeVC
140-
}
141-
}
142-
143136
private func navigateToDetailVC() {
144137
let vc = SignUpDetailViewController()
145138
navigationController?.pushViewController(vc, animated: true)

GoMoney/Scences/Profile/ProfileViewController.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,18 @@ class ProfileViewController: GMMainViewController {
169169
let navVC = UINavigationController(rootViewController: signInVC)
170170

171171
if let delegate = view.window?.windowScene?.delegate as? SceneDelegate {
172-
delegate.window?.rootViewController = navVC
172+
if let window = delegate.window {
173+
window.rootViewController = navVC
174+
175+
let options: UIView.AnimationOptions = .transitionCrossDissolve
176+
let duration: TimeInterval = 0.5
177+
UIView.transition(
178+
with: window,
179+
duration: duration,
180+
options: options,
181+
animations: {},
182+
completion: { _ in })
183+
}
173184
}
174185
}
175186

GoMoney/Service/AuthService.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,33 @@ class AuthService {
120120
// remove realm
121121
DataService.shared.dropAllTable()
122122
}
123+
124+
func restoreUserData(completion: @escaping (Error?) -> Void) {
125+
RemoteService.shared.getAllTags { result in
126+
switch result {
127+
case .failure(let err):
128+
completion(err)
129+
case .success(let tags):
130+
TagService.shared.setTags(tags: tags) { err in
131+
if let err = err {
132+
completion(err)
133+
}
134+
else {
135+
print("[restore] \(tags.count) tags")
136+
RemoteService.shared.getAllTransactions { result in
137+
switch result {
138+
case .success(let transactions):
139+
print("[restore] \(transactions.count) transactions")
140+
DataService.shared.addTransactions(transactions) { err in
141+
completion(err)
142+
}
143+
case .failure(let err):
144+
completion(err)
145+
}
146+
}
147+
}
148+
}
149+
}
150+
}
151+
}
123152
}

GoMoney/Service/DataService.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum DataError: Error {
1313
case transactionNotFound(_ transaction: Expense)
1414
case noTransactions
1515
case userNotFound
16+
case tagNotFound
1617

1718
var localizedDescription: String {
1819
switch self {
@@ -22,6 +23,8 @@ enum DataError: Error {
2223
return "There is no transactions!"
2324
case .userNotFound:
2425
return "User not found!"
26+
case .tagNotFound:
27+
return "Tag not found!"
2528
}
2629
}
2730
}
@@ -111,6 +114,17 @@ class DataService {
111114
}
112115
}
113116

117+
func addTransactions(_ transactions: [Expense], completion: (Error?) -> Void) {
118+
do {
119+
try realm.write {
120+
realm.add(transactions)
121+
}
122+
completion(nil)
123+
} catch {
124+
completion(error)
125+
}
126+
}
127+
114128
func deleteExpense(expense: Expense, completion: ((Error?) -> Void)? = nil) {
115129
do {
116130
try realm.write {

0 commit comments

Comments
 (0)