Skip to content

Commit

Permalink
Refactored combine methods and fixed image update issue
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-amisha-i committed Apr 5, 2024
1 parent 208a3db commit f5310d8
Show file tree
Hide file tree
Showing 16 changed files with 241 additions and 241 deletions.
61 changes: 33 additions & 28 deletions Data/Data/Helper/Firebase/StorageManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by Amisha Italiya on 07/03/24.
//

import Foundation
import Combine
import FirebaseStorage

public class StorageManager: ObservableObject {
Expand All @@ -26,50 +26,55 @@ public class StorageManager: ObservableObject {

private let storage = Storage.storage()

public func uploadImage(for storeType: ImageStoreType, id: String, imageData: Data, completion: @escaping (String?) -> Void) {
public func uploadImage(for storeType: ImageStoreType, id: String, imageData: Data) -> AnyPublisher<String, ServiceError> {
let storageRef = storage.reference(withPath: "/\(storeType.pathName)/\(id)")

let metadata = StorageMetadata()
metadata.contentType = "image/jpg"

storageRef.putData(imageData, metadata: metadata) { _, error in
if let error {
LogE("StorageManager: Error while uploading file: \(error.localizedDescription)")
completion(nil)
return
}

storageRef.downloadURL { url, error in
return Future { promise in
storageRef.putData(imageData, metadata: metadata) { _, error in
if let error {
LogE("StorageManager: Download url failed with error: \(error.localizedDescription)")
completion(nil) // Return nil for completion to indicate error
} else if let imageUrl = url?.absoluteString {
LogD("StorageManager: Image successfully uploaded to Firebase!")
completion(imageUrl)
LogE("StorageManager: Error while uploading file: \(error.localizedDescription)")
promise(.failure(.databaseError))
} else {
storageRef.downloadURL { url, error in
if let error {
LogE("StorageManager: Download url failed with error: \(error.localizedDescription)")
promise(.failure(.databaseError))
} else if let imageUrl = url?.absoluteString {
LogD("StorageManager: Image successfully uploaded to Firebase!")
promise(.success(imageUrl))
}
}
}
}
}
.eraseToAnyPublisher()
}

public func updateImage(for type: ImageStoreType, id: String, url: String, imageData: Data, completion: @escaping (String?) -> Void) {
deleteImage(imageUrl: url) { error in
guard error == nil else { completion(nil) ; return }

self.uploadImage(for: type, id: id, imageData: imageData, completion: completion)
}
public func updateImage(for type: ImageStoreType, id: String, url: String, imageData: Data) -> AnyPublisher<String, ServiceError> {
self.deleteImage(imageUrl: url)
.flatMap { _ in
self.uploadImage(for: type, id: id, imageData: imageData)
}
.eraseToAnyPublisher()
}

public func deleteImage(imageUrl: String, completion: @escaping (Error?) -> Void) {
public func deleteImage(imageUrl: String) -> AnyPublisher<Void, ServiceError> {
let storageRef = storage.reference(forURL: imageUrl)

storageRef.delete { error in
guard error == nil else {
LogE("StorageManager: Error while deleting image: \(error as Any)")
completion(error)
return
return Future { promise in
storageRef.delete { error in
if let error {
LogE("StorageManager: Error while deleting image: \(error)")
promise(.failure(.databaseError))
} else {
promise(.success(()))
}
}
completion(nil)
}
.eraseToAnyPublisher()
}
}

Expand Down
4 changes: 2 additions & 2 deletions Data/Data/Repository/ExpenseRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public class ExpenseRepository: ObservableObject {

private var cancelable = Set<AnyCancellable>()

public func addExpense(expense: Expense, completion: @escaping (String?) -> Void) {
store.addExpense(expense: expense, completion: completion)
public func addExpense(expense: Expense) -> AnyPublisher<Void, ServiceError> {
store.addExpense(expense: expense)
}

public func deleteExpense(id: String) -> AnyPublisher<Void, ServiceError> {
Expand Down
163 changes: 61 additions & 102 deletions Data/Data/Repository/GroupRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,63 @@ public class GroupRepository: ObservableObject {
private var cancelable = Set<AnyCancellable>()

public func createGroup(group: Groups, imageData: Data?) -> AnyPublisher<String, ServiceError> {
Future { [weak self] promise in
guard let self else { promise(.failure(.unexpectedError)); return }

self.store.createGroup(group: group) { docId in
guard let docId else {
promise(.failure(.databaseError))
return
return store.createGroup(group: group)
.flatMap { [weak self] groupId -> AnyPublisher<String, ServiceError> in
guard let self else { return Fail(error: .unexpectedError).eraseToAnyPublisher() }
guard let imageData else {
return Just(groupId).setFailureType(to: ServiceError.self).eraseToAnyPublisher()
}

if let imageData {
var newGroup = group
newGroup.id = docId
self.uploadImage(imageData: imageData, group: newGroup)
.sink { completion in
switch completion {
case .finished:
return
case .failure(let error):
promise(.failure(error))
}
} receiveValue: { _ in
promise(.success(docId))
}.store(in: &self.cancelable)
} else {
promise(.success(docId))
}
var newGroup = group
newGroup.id = groupId

return self.uploadImage(imageData: imageData, group: newGroup)
.map { _ in groupId }
.eraseToAnyPublisher()
}
}.eraseToAnyPublisher()
.eraseToAnyPublisher()
}

private func uploadImage(imageData: Data, group: Groups) -> AnyPublisher<Void, ServiceError> {
guard let groupId = group.id else {
return Fail(error: .unexpectedError).eraseToAnyPublisher()
}

return storageManager.uploadImage(for: .group, id: groupId, imageData: imageData)
.flatMap { imageUrl -> AnyPublisher<Void, ServiceError> in
var newGroup = group
newGroup.imageUrl = imageUrl
return self.updateGroup(group: newGroup)
}
.eraseToAnyPublisher()
}

public func updateGroup(group: Groups) -> AnyPublisher<Void, ServiceError> {
store.updateGroup(group: group)
}

public func updateGroupWithImage(imageData: Data?, newImageUrl: String?, group: Groups) -> AnyPublisher<Void, ServiceError> {
var newGroup = group

if let currentUrl = group.imageUrl, newImageUrl == nil {
newGroup.imageUrl = newImageUrl

return storageManager.deleteImage(imageUrl: currentUrl)
.flatMap { _ in
if let imageData {
self.uploadImage(imageData: imageData, group: newGroup)
} else {
self.updateGroup(group: newGroup)
}
}
.eraseToAnyPublisher()
}

if let imageData {
return self.uploadImage(imageData: imageData, group: newGroup)
} else {
return updateGroup(group: newGroup)
}
}

public func fetchGroupBy(id: String) -> AnyPublisher<Groups?, ServiceError> {
Expand All @@ -69,87 +98,18 @@ public class GroupRepository: ObservableObject {
}.eraseToAnyPublisher()
}

public func updateGroup(group: Groups) -> AnyPublisher<Void, ServiceError> {
store.updateGroup(group: group)
}

private func uploadImage(imageData: Data, group: Groups) -> AnyPublisher<Void, ServiceError> {
Future { [weak self] promise in

guard let self, let groupId = group.id else { promise(.failure(.unexpectedError)); return }

self.storageManager.uploadImage(for: .group, id: groupId, imageData: imageData) { url in
guard let url else {
promise(.failure(.databaseError))
return
}

var newGroup = group
newGroup.imageUrl = url

self.updateGroup(group: newGroup)
.sink { completion in
if case .failure(let error) = completion {
promise(.failure(error))
}
} receiveValue: { _ in
promise(.success(()))
}.store(in: &self.cancelable)
}
}.eraseToAnyPublisher()
}

public func updateGroupWithImage(imageData: Data?, group: Groups) -> AnyPublisher<Void, ServiceError> {
Future { [weak self] promise in
guard let self, let url = group.imageUrl else {
promise(.failure(.unexpectedError))
return
}

let updateGroup = {
self.updateGroup(group: group)
.sink { completion in
if case .failure(let error) = completion {
promise(.failure(error))
}
} receiveValue: { _ in
promise(.success(()))
}
.store(in: &self.cancelable)
}

if let imageData {
self.storageManager.deleteImage(imageUrl: url) { error in
guard error == nil else {
promise(.failure(.databaseError))
return
}

self.uploadImage(imageData: imageData, group: group)
.sink { completion in
if case .failure(let error) = completion {
promise(.failure(error))
}
} receiveValue: { _ in
promise(.success(()))
}
.store(in: &self.cancelable)
}
} else {
updateGroup()
}
}.eraseToAnyPublisher()
}

public func addMemberToGroup(memberId: String, groupId: String) -> AnyPublisher<Void, ServiceError> {
return fetchGroupBy(id: groupId)
.flatMap { group -> AnyPublisher<Void, ServiceError> in
guard let group else { return Fail(error: .dataNotFound).eraseToAnyPublisher() }
guard var group else { return Fail(error: .dataNotFound).eraseToAnyPublisher() }

var newGroup = group
newGroup.members.append(memberId)
// Check if the member already exists in the group
if group.members.contains(memberId) {
return Fail(error: .alreadyExists).eraseToAnyPublisher()
}

return self.updateGroup(group: newGroup)
group.members.append(memberId)
return self.updateGroup(group: group)
}
.eraseToAnyPublisher()
}
Expand All @@ -169,7 +129,6 @@ public class GroupRepository: ObservableObject {
return Publishers.MergeMany(memberPublishers)
.compactMap { $0 }
.collect()
.mapError { $0 }
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
Expand Down
32 changes: 18 additions & 14 deletions Data/Data/Repository/ShareCodeRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class ShareCodeRepository: ObservableObject {

private var cancelable = Set<AnyCancellable>()

public func addSharedCode(sharedCode: SharedCode, completion: @escaping (String?) -> Void) {
store.addSharedCode(sharedCode: sharedCode, completion: completion)
public func addSharedCode(sharedCode: SharedCode) -> AnyPublisher<Void, ServiceError> {
store.addSharedCode(sharedCode: sharedCode)
}

public func fetchSharedCode(code: String) -> Future<SharedCode?, ServiceError> {
Expand All @@ -27,17 +27,21 @@ public class ShareCodeRepository: ObservableObject {
store.deleteSharedCode(documentId: documentId)
}

public func checkForCodeAvailability(code: String, completion: @escaping (Bool) -> Void) {
fetchSharedCode(code: code)
.sink { result in
switch result {
case .failure:
completion(true)
case .finished:
return
}
} receiveValue: { code in
completion(code == nil)
}.store(in: &cancelable)
public func checkForCodeAvailability(code: String) -> AnyPublisher<Bool, ServiceError> {
return Future { [weak self] promise in
guard let self else { promise(.failure(.unexpectedError)); return }
self.fetchSharedCode(code: code)
.sink { result in
switch result {
case .failure(let error):
promise(.failure(error))
case .finished:
promise(.success(true))
}
} receiveValue: { code in
promise(.success(code == nil))
}.store(in: &self.cancelable)
}
.eraseToAnyPublisher()
}
}
9 changes: 4 additions & 5 deletions Data/Data/Repository/UserRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class UserRepository: ObservableObject {
private var cancelable = Set<AnyCancellable>()

public func storeUser(user: AppUser) -> AnyPublisher<AppUser, ServiceError> {
return self.store.fetchUsers()
self.store.fetchUsers()
.flatMap { [weak self] users -> AnyPublisher<AppUser, ServiceError> in
guard let self else {
return Fail(error: .unexpectedError).eraseToAnyPublisher()
Expand All @@ -29,15 +29,14 @@ public class UserRepository: ObservableObject {
return .databaseError
}
.map { _ in user }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
.eraseToAnyPublisher()
}

public func fetchUserBy(userID: String) -> AnyPublisher<AppUser?, ServiceError> {
return self.store.fetchUsers()
self.store.fetchUsers()
.map { users -> AppUser? in
return users.first(where: { $0.id == userID })
}
Expand All @@ -49,10 +48,10 @@ public class UserRepository: ObservableObject {
}

public func updateUser(user: AppUser) -> AnyPublisher<Void, ServiceError> {
return store.updateUser(user: user)
store.updateUser(user: user)
}

public func deleteUser(id: String) -> AnyPublisher<Void, ServiceError> {
return store.deleteUser(id: id)
store.deleteUser(id: id)
}
}
Loading

0 comments on commit f5310d8

Please sign in to comment.