Skip to content

Commit

Permalink
Managed errors and state
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-nirali-s committed Oct 23, 2024
1 parent dafd297 commit 2c5001b
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 143 deletions.
2 changes: 1 addition & 1 deletion Data/Data.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@
D89DBE262B88801F00E5F1BD /* Model */ = {
isa = PBXGroup;
children = (
21559CA32CBD05570039F127 /* ActivityLog.swift */,
D89DBE272B88802800E5F1BD /* Country.swift */,
D89DBE472B8CBE4C00E5F1BD /* AppUser.swift */,
21559CA32CBD05570039F127 /* ActivityLog.swift */,
D83B15042B9996C0004A5F4F /* Groups.swift */,
D85E86DD2BAB0292002EDF76 /* Expense.swift */,
D8CF5A202C1986250014E3AD /* Transaction.swift */,
Expand Down
2 changes: 1 addition & 1 deletion Data/Data/Repository/ExpenseRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ExpenseRepository: ObservableObject {

public func deleteExpense(groupId: String, expense: Expense) async throws {
var expense = expense
expense.isActive = false // Make expense inactive
expense.isActive = false // Make expense inactive

try await updateExpense(groupId: groupId, expense: expense)
}
Expand Down
2 changes: 1 addition & 1 deletion Data/Data/Repository/TransactionRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class TransactionRepository: ObservableObject {

public func deleteTransaction(groupId: String, transaction: Transactions) async throws {
var transaction = transaction
transaction.isActive = false // Make transaction inactive
transaction.isActive = false // Make transaction inactive

try await updateTransaction(groupId: groupId, transaction: transaction)
}
Expand Down
1 change: 0 additions & 1 deletion Splito/UI/Home/Account/AccountHomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import SwiftUI
import BaseStyle

struct AccountHomeView: View {
@EnvironmentObject var homeRouteViewModel: HomeRouteViewModel

@StateObject var viewModel: AccountHomeViewModel

Expand Down
10 changes: 8 additions & 2 deletions Splito/UI/Home/ActivityLog/ActivityLogViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ class ActivityLogViewModel: BaseViewModel, ObservableObject {

// MARK: - Data Loading
private func fetchActivityLogs() async {
guard let userId = preference.user?.id else { return }
guard let userId = preference.user?.id else {
viewState = .initial
return
}

do {
viewState = .loading
Expand Down Expand Up @@ -101,7 +104,10 @@ class ActivityLogViewModel: BaseViewModel, ObservableObject {
}

private func fetchLatestActivityLogs() {
guard let userId = preference.user?.id else { return }
guard let userId = preference.user?.id else {
viewState = .initial
return
}

Task {
do {
Expand Down
42 changes: 29 additions & 13 deletions Splito/UI/Home/Expense/AddExpenseViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,8 @@ extension AddExpenseViewModel {
let newExpense = try await expenseRepository.addExpense(groupId: groupId, expense: expense)
let expenseInfo: [String: Any] = ["groupId": groupId, "expense": newExpense]
NotificationCenter.default.post(name: .addExpense, object: nil, userInfo: expenseInfo)

if !(selectedGroup?.hasExpenses ?? false) { selectedGroup?.hasExpenses = true }

await updateGroupMemberBalance(expense: expense, updateType: .Add)
await addLogForAddExpense(expense: newExpense)

Expand All @@ -345,27 +344,34 @@ extension AddExpenseViewModel {
}

private func addLogForAddExpense(expense: Expense) async {
guard let userId = preference.user?.id else { return }
guard let userId = preference.user?.id else {
showLoader = false
return
}

var errors: [Error] = []
var involvedUserIds = Set(expense.splitTo).union(expense.paidBy.keys)
involvedUserIds.insert(userId)

await withTaskGroup(of: Void.self) { groupTasks in
for memberId in involvedUserIds {
groupTasks.addTask { [weak self] in
guard let self else { return }
await addActivityLog(expense: expense, type: .expenseAdded, memberId: memberId)
await self?.addActivityLog(expense: expense, type: .expenseAdded, memberId: memberId, errors: &errors)
}
}
}
if !errors.isEmpty {
showLoader = false
showToastForError()
}
}

private func updateExpense(groupId: String, expense: Expense, oldExpense: Expense, completion: (Bool) -> Void) async {
do {
showLoader = true

try await expenseRepository.updateExpense(groupId: groupId, expense: expense)
NotificationCenter.default.post(name: .updateExpense, object: expense)

await updateGroupMemberBalance(expense: expense, updateType: .Update(oldExpense: oldExpense))
await addLogForUpdateExpense(updatedExpense: expense, oldExpense: oldExpense)

Expand All @@ -379,31 +385,41 @@ extension AddExpenseViewModel {
}

private func addLogForUpdateExpense(updatedExpense: Expense, oldExpense: Expense) async {
guard let userId = preference.user?.id else { return }
guard let userId = preference.user?.id else {
showLoader = false
return
}

var errors: [Error] = []
var involvedUserIds = Set(oldExpense.splitTo).union(oldExpense.paidBy.keys)
involvedUserIds = involvedUserIds.union(updatedExpense.splitTo).union(updatedExpense.paidBy.keys)
involvedUserIds.insert(userId)

await withTaskGroup(of: Void.self) { groupTasks in
for memberId in involvedUserIds {
groupTasks.addTask { [weak self] in
guard let self else { return }
await addActivityLog(expense: updatedExpense, type: .expenseUpdated, memberId: memberId)
await self?.addActivityLog(expense: updatedExpense, type: .expenseUpdated, memberId: memberId, errors: &errors)
}
}
}

if !errors.isEmpty {
showLoader = false
showToastForError()
}
}

private func addActivityLog(expense: Expense, type: ActivityType, memberId: String) async {
guard let user = preference.user else { return }
private func addActivityLog(expense: Expense, type: ActivityType, memberId: String, errors: inout [Error]) async {
guard let user = preference.user else {
showLoader = false
return
}

if let activity = createActivityLogForExpense(context: ActivityLogContext(group: selectedGroup, expense: expense, type: type, memberId: memberId, currentUser: user)) {
do {
try await activityLogRepository.addActivityLog(userId: memberId, activity: activity)
} catch {
LogE("Failed to add activity log for user \(memberId): \(error)")
showToastForError()
errors.append(error)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import Data
import SwiftUI
import FirebaseFirestore

class ExpenseDetailsViewModel: BaseViewModel, ObservableObject {

Expand Down Expand Up @@ -134,8 +133,7 @@ class ExpenseDetailsViewModel: BaseViewModel, ObservableObject {
viewState = .initial
router.pop()
} catch {
viewState = .initial
showToastForError()
handleServiceError()
}
}
}
Expand All @@ -159,9 +157,9 @@ class ExpenseDetailsViewModel: BaseViewModel, ObservableObject {
expense.updatedBy = userId

try await expenseRepository.deleteExpense(groupId: groupId, expense: expense)
NotificationCenter.default.post(name: .deleteExpense, object: expense)
await self.updateGroupMemberBalance(updateType: .Delete)
await addLogForDeletedExpense(type: .expenseDeleted)
NotificationCenter.default.post(name: .deleteExpense, object: expense)

viewState = .initial
router.pop()
Expand Down Expand Up @@ -189,7 +187,10 @@ class ExpenseDetailsViewModel: BaseViewModel, ObservableObject {
}

private func addLogForDeletedExpense(type: ActivityType) async {
guard let group, let expense, let user = preference.user else { return }
guard let group, let expense, let user = preference.user else {
viewState = .initial
return
}

var errors: [Error] = []
var involvedUserIds = Set(expense.splitTo).union(expense.paidBy.keys)
Expand All @@ -198,10 +199,9 @@ class ExpenseDetailsViewModel: BaseViewModel, ObservableObject {
await withTaskGroup(of: Void.self) { groupTasks in
for memberId in involvedUserIds {
groupTasks.addTask { [weak self] in
guard let self else { return }
if let activity = createActivityLogForExpense(context: ActivityLogContext(group: group, expense: expense, type: type, memberId: memberId, currentUser: user)) {
do {
try await activityLogRepository.addActivityLog(userId: memberId, activity: activity)
try await self?.activityLogRepository.addActivityLog(userId: memberId, activity: activity)
} catch {
errors.append(error)
}
Expand All @@ -211,7 +211,7 @@ class ExpenseDetailsViewModel: BaseViewModel, ObservableObject {
}

if !errors.isEmpty {
LogE("Failed to add activity logs for delete expense: \(errors)")
viewState = .initial
showToastForError()
}
}
Expand Down
49 changes: 37 additions & 12 deletions Splito/UI/Home/Groups/Create Group/CreateGroupViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,18 @@ class CreateGroupViewModel: BaseViewModel, ObservableObject {
}

private func addLogForCreateGroup(group: Groups) async {
guard let userId = preference.user?.id else { return }
await addActivityLog(group: group, type: .groupCreated, memberId: userId)
guard let userId = preference.user?.id else {
showLoader = false
return
}

var errors: [Error] = []
await addActivityLog(group: group, type: .groupCreated, memberId: userId, errors: &errors)

if !errors.isEmpty {
showLoader = false
showToastForError()
}
}

private func updateGroup(group: Groups, completion: (Bool) -> Void) async {
Expand Down Expand Up @@ -143,34 +153,49 @@ class CreateGroupViewModel: BaseViewModel, ObservableObject {
}

private func addLogForUpdateGroup(updatedGroup: Groups) async {
let currentGroupName = group?.name ?? ""
let currentImageUrl = group?.imageUrl
guard let group else {
showLoader = false
return
}

let currentGroupName = group.name
let currentImageUrl = group.imageUrl
let hasNameChanged = currentGroupName.trimmingCharacters(in: .whitespacesAndNewlines) != updatedGroup.name
let hasImageChanged = currentImageUrl != updatedGroup.imageUrl

if !hasNameChanged && !hasImageChanged { return }
if !hasNameChanged && !hasImageChanged {
showLoader = false
return
}

let type: ActivityType = (group?.imageUrl != updatedGroup.imageUrl && group?.name != updatedGroup.name) ? .groupUpdated : group?.imageUrl != updatedGroup.imageUrl ? .groupImageUpdated : .groupNameUpdated
var errors: [Error] = []
let type: ActivityType = (group.imageUrl != updatedGroup.imageUrl && group.name != updatedGroup.name) ? .groupUpdated : group.imageUrl != updatedGroup.imageUrl ? .groupImageUpdated : .groupNameUpdated

await withTaskGroup(of: Void.self) { groupTasks in
for memberId in Set(updatedGroup.members) {
groupTasks.addTask { [weak self] in
guard let self else { return }
await addActivityLog(group: updatedGroup, type: type, memberId: memberId, previousGroupName: (type == .groupNameUpdated || type == .groupUpdated) ? group?.name : nil)
await self?.addActivityLog(group: updatedGroup, type: type, memberId: memberId, previousGroupName: (type == .groupNameUpdated || type == .groupUpdated) ? group.name : nil, errors: &errors)
}
}
}

if !errors.isEmpty {
showLoader = false
showToastForError()
}
}

private func addActivityLog(group: Groups, type: ActivityType, memberId: String, previousGroupName: String? = nil) async {
guard let user = preference.user else { return }
private func addActivityLog(group: Groups, type: ActivityType, memberId: String, previousGroupName: String? = nil, errors: inout [Error]) async {
guard let user = preference.user else {
showLoader = false
return
}

if let activity = createActivityLogForGroup(context: ActivityLogContext(group: group, type: type, memberId: memberId, currentUser: user, previousGroupName: previousGroupName)) {
do {
try await activityLogRepository.addActivityLog(userId: memberId, activity: activity)
} catch {
LogE("Failed to add activity log for user \(memberId): \(error)")
showToastForError()
errors.append(error)
}
}
}
Expand Down
Loading

0 comments on commit 2c5001b

Please sign in to comment.