Skip to content

Commit

Permalink
Add attachment to payment/expense
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-amisha-i committed Nov 28, 2024
1 parent 99682f7 commit 9f9d96d
Show file tree
Hide file tree
Showing 66 changed files with 1,103 additions and 626 deletions.
12 changes: 8 additions & 4 deletions BaseStyle/BaseStyle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
D8E244C12B986CD800C6C82A /* ImagePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E244C02B986CD800C6C82A /* ImagePickerView.swift */; };
D8E244C32B986D4F00C6C82A /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E244C22B986D4F00C6C82A /* UIImage+Extension.swift */; };
D8EB0ED82CAD8C9F00AC6A44 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8EB0ED72CAD8C9F00AC6A44 /* ErrorView.swift */; };
D8FFD5C72CF44DBC009A0667 /* ZoomableImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FFD5C62CF44DBC009A0667 /* ZoomableImageView.swift */; };
D8EB5E952CF8B12B005B68D9 /* ZoomableImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8EB5E942CF8B12B005B68D9 /* ZoomableImageView.swift */; };
D8FFD5C72CF44DBC009A0667 /* AttachmentZoomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FFD5C62CF44DBC009A0667 /* AttachmentZoomView.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -121,7 +122,8 @@
D8E244C02B986CD800C6C82A /* ImagePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePickerView.swift; sourceTree = "<group>"; };
D8E244C22B986D4F00C6C82A /* UIImage+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = "<group>"; };
D8EB0ED72CAD8C9F00AC6A44 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
D8FFD5C62CF44DBC009A0667 /* ZoomableImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoomableImageView.swift; sourceTree = "<group>"; };
D8EB5E942CF8B12B005B68D9 /* ZoomableImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoomableImageView.swift; sourceTree = "<group>"; };
D8FFD5C62CF44DBC009A0667 /* AttachmentZoomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentZoomView.swift; sourceTree = "<group>"; };
E0B1A6930B9FF35E9142463B /* Pods-BaseStyle.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BaseStyle.debug.xcconfig"; path = "Target Support Files/Pods-BaseStyle/Pods-BaseStyle.debug.xcconfig"; sourceTree = "<group>"; };
E4AFAF996FB5C233D40D81D5 /* Pods_BaseStyleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BaseStyleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -274,7 +276,8 @@
21BEF8A42C637E4900FBC9CF /* NavigationBarTopView.swift */,
21D614782CAD527D00779F1E /* NavigationTitleTextView.swift */,
219F43D82CCA4A7000729C67 /* RestoreButton.swift */,
D8FFD5C62CF44DBC009A0667 /* ZoomableImageView.swift */,
D8EB5E942CF8B12B005B68D9 /* ZoomableImageView.swift */,
D8FFD5C62CF44DBC009A0667 /* AttachmentZoomView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -506,7 +509,7 @@
D82174BE2BBAD86D00DB42C3 /* ProfileImageView.swift in Sources */,
213F377E2C416C9C00972316 /* ScrollToTopButton.swift in Sources */,
D89C933F2BC3C0F800FACD16 /* ForwardIcon.swift in Sources */,
D8FFD5C72CF44DBC009A0667 /* ZoomableImageView.swift in Sources */,
D8FFD5C72CF44DBC009A0667 /* AttachmentZoomView.swift in Sources */,
D89DBE352B88A05F00E5F1BD /* UIApplication+Extension.swift in Sources */,
D8D42A772B85CE2A009B345D /* ButtonStyleTapGestureModifier.swift in Sources */,
21BEF8A52C637E4900FBC9CF /* NavigationBarTopView.swift in Sources */,
Expand All @@ -518,6 +521,7 @@
D8D42A8A2B85D525009B345D /* AppColors.swift in Sources */,
D8D42AAC2B872A7C009B345D /* ToastView.swift in Sources */,
217620462C4F7CE700FED0D4 /* BackButton.swift in Sources */,
D8EB5E952CF8B12B005B68D9 /* ZoomableImageView.swift in Sources */,
D8D42A952B85F8A2009B345D /* Bundle+Extension.swift in Sources */,
21D26E232CA199630090488B /* CapsuleButton.swift in Sources */,
D89C93462BC42DE500FACD16 /* MailComposeView.swift in Sources */,
Expand Down
10 changes: 4 additions & 6 deletions BaseStyle/BaseStyle/CustomUI/ImagePickerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
import SwiftUI

public struct ImagePickerView: UIViewControllerRepresentable {
@Environment(\.colorScheme) var colorScheme

@Binding var image: UIImage?
@Binding var isPresented: Bool

var cropOption: CropOption
var sourceType: UIImagePickerController.SourceType = .photoLibrary

public init(cropOption: CropOption, sourceType: UIImagePickerController.SourceType, image: Binding<UIImage?>, isPresented: Binding<Bool>) {
public init(cropOption: CropOption, sourceType: UIImagePickerController.SourceType,
image: Binding<UIImage?>, isPresented: Binding<Bool>) {
self._image = image
self.sourceType = sourceType
self._isPresented = isPresented
self.cropOption = cropOption
}

public func makeCoordinator() -> ImagePickerViewCoordinator {
return ImagePickerViewCoordinator(image: $image, isPresented: $isPresented, cropOption: cropOption, isDarkMode: colorScheme == .dark)
return ImagePickerViewCoordinator(image: $image, isPresented: $isPresented, cropOption: cropOption)
}

public func makeUIViewController(context: Context) -> UIImagePickerController {
Expand Down Expand Up @@ -55,13 +55,11 @@ public class ImagePickerViewCoordinator: NSObject, UINavigationControllerDelegat
@Binding var isPresented: Bool

var cropOption: ImagePickerView.CropOption
var isDarkMode: Bool

init(image: Binding<UIImage?>, isPresented: Binding<Bool>, cropOption: ImagePickerView.CropOption, isDarkMode: Bool) {
init(image: Binding<UIImage?>, isPresented: Binding<Bool>, cropOption: ImagePickerView.CropOption) {
self._image = image
self._isPresented = isPresented
self.cropOption = cropOption
self.isDarkMode = isDarkMode
}

public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
Expand Down
4 changes: 2 additions & 2 deletions BaseStyle/BaseStyle/CustomUI/MailComposeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct MailComposeView: UIViewControllerRepresentable {

public func makeUIViewController(context: Context) -> MFMailComposeViewController {
guard MFMailComposeViewController.canSendMail() else {
print("MailComposeView: Device cannot send email.")
print("MailComposeView: \(#function) Device cannot send email.")
return MFMailComposeViewController()
}

Expand All @@ -35,7 +35,7 @@ public struct MailComposeView: UIViewControllerRepresentable {
let attachmentData = try Data(contentsOf: logFilePath)
mailComposeViewController.addAttachmentData(attachmentData, mimeType: "application/zip", fileName: "logs.zip")
} catch {
print("MailComposeView: Failed to load attachment data: \(error.localizedDescription)")
print("MailComposeView: \(#function) Failed to load attachment data: \(error).")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.040",
"alpha" : "0.080",
"blue" : "0xDB",
"green" : "0xDD",
"red" : "0xDD"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x3F",
"green" : "0x36",
"red" : "0x36"
"blue" : "0x33",
"green" : "0x30",
"red" : "0x30"
}
},
"idiom" : "universal"
Expand Down
92 changes: 92 additions & 0 deletions BaseStyle/BaseStyle/Views/AttachmentZoomView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// AttachmentZoomView.swift
// Splito
//
// Created by Amisha Italiya on 25/11/24.
//

import SwiftUI
import Kingfisher

// MARK: - AttachmentContainerView

public struct AttachmentContainerView: View {

@Binding var showImageDisplayView: Bool

var image: UIImage?
var imageUrl: String?

@Namespace private var animationNamespace

public init(showImageDisplayView: Binding<Bool>, image: UIImage? = nil, imageUrl: String? = nil) {
self._showImageDisplayView = showImageDisplayView
self.image = image
self.imageUrl = imageUrl
}

public var body: some View {
ZStack {
if let image {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
} else if let imageUrl, let url = URL(string: imageUrl) {
KFImage(url)
.placeholder { _ in
ImageLoaderView()
}
.setProcessor(DownsamplingImageProcessor(size: UIScreen.main.bounds.size)) // Downsample to fit screen size
.cacheMemoryOnly()
.resizable()
.aspectRatio(contentMode: .fill)
}
}
.matchedGeometryEffect(id: "image", in: animationNamespace)
.onTapGestureForced {
showImageDisplayView = true
}
}
}

// MARK: - AttachmentZoomView

public struct AttachmentZoomView: View {
@Environment(\.dismiss) var dismiss

var image: UIImage?
var imageUrl: String?

@Namespace var animationNamespace

public init(image: UIImage? = nil, imageUrl: String? = nil) {
self.image = image
self.imageUrl = imageUrl
}

public var body: some View {
GeometryReader { geometry in
ZStack {
if #available(iOS 18.0, *) {
ZoomableImageView(image: image, imageUrl: imageUrl, geometry: geometry)
.matchedGeometryEffect(id: "image", in: animationNamespace)
.navigationTransition(.zoom(sourceID: "zoom", in: animationNamespace))
} else {
ZoomableImageView(image: image, imageUrl: imageUrl, geometry: geometry)
}
}
}
.navigationBarBackButtonHidden()
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
dismiss()
} label: {
Image(systemName: "xmark.circle.fill")
.font(.system(size: 18))
.foregroundStyle(disableText)
}
}
}
}
}
80 changes: 4 additions & 76 deletions BaseStyle/BaseStyle/Views/ZoomableImageView.swift
Original file line number Diff line number Diff line change
@@ -1,88 +1,16 @@
//
// ZoomableImageView.swift
// Splito
// BaseStyle
//
// Created by Amisha Italiya on 25/11/24.
// Created by Amisha Italiya on 28/11/24.
//

import SwiftUI
import Kingfisher

// MARK: - ExpenseImageView

public struct ExpenseImageView: View {

@Binding var showImageDisplayView: Bool

var image: UIImage?
var imageUrl: String?

@Namespace private var animationNamespace

public var body: some View {
ZStack {
if let image {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
} else if let imageUrl, let url = URL(string: imageUrl) {
KFImage(url)
.placeholder { _ in
ImageLoaderView()
}
.setProcessor(DownsamplingImageProcessor(size: UIScreen.main.bounds.size)) // Downsample to fit screen size
.cacheMemoryOnly()
.resizable()
.aspectRatio(contentMode: .fill)
}
}
.matchedGeometryEffect(id: "image", in: animationNamespace)
.onTapGestureForced {
showImageDisplayView = true
}
}
}

// MARK: - ExpenseImageZoomView

public struct ExpenseImageZoomView: View {
@Environment(\.dismiss) var dismiss

var image: UIImage?
var imageUrl: String?

@Namespace var animationNamespace

public var body: some View {
GeometryReader { geometry in
ZStack {
if #available(iOS 18.0, *) {
ZoomableImageView(image: image, imageUrl: imageUrl, geometry: geometry)
.matchedGeometryEffect(id: "image", in: animationNamespace)
.navigationTransition(.zoom(sourceID: "zoom", in: animationNamespace))
} else {
ZoomableImageView(image: image, imageUrl: imageUrl, geometry: geometry)
}
}
}
.navigationBarBackButtonHidden()
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
dismiss()
} label: {
Image(systemName: "xmark.circle.fill")
.font(.system(size: 18))
.foregroundStyle(disableText)
}
}
}
}
}

// MARK: - ZoomableImageView

private struct ZoomableImageView: View {
public struct ZoomableImageView: View {

var image: UIImage?
var imageUrl: String?
Expand Down Expand Up @@ -132,7 +60,7 @@ private struct ZoomableImageView: View {
}
}

var body: some View {
public var body: some View {
ZStack {
if let image {
Image(uiImage: image)
Expand Down
6 changes: 3 additions & 3 deletions Data/Data/Extension/Query+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ extension Query {
/// includeMetadataChanges: false: This option ensures that your listener will only be triggered by actual data changes, not by metadata changes (like network acknowledgment or pending writes).
let listener = self.addSnapshotListener(includeMetadataChanges: false) { querySnapshot, error in
if let error {
LogE("SnapshotPublisher :: error: \(error.localizedDescription)")
LogE("SnapshotPublisher: \(#function) error: \(error).")
publisher.send(completion: .failure(.databaseError(error: error)))
return
}

guard let documents = querySnapshot?.documents else {
LogE("SnapshotPublisher :: The document is not available.")
LogE("SnapshotPublisher: \(#function) The document is not available.")
publisher.send(completion: .finished)
return
}
Expand All @@ -42,7 +42,7 @@ extension Query {
}
publisher.send(decodedDocuments)
} catch {
LogE("SnapshotPublisher :: Decode error: \(error.localizedDescription)")
LogE("SnapshotPublisher: \(#function) Decode error: \(error).")
publisher.send(completion: .failure(.decodingError))
}
}
Expand Down
10 changes: 7 additions & 3 deletions Data/Data/Helper/Firebase/StorageManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class StorageManager: ObservableObject {
case user
case group
case expense
case payment

var pathName: String {
switch self {
Expand All @@ -22,6 +23,8 @@ public class StorageManager: ObservableObject {
"group_images"
case .expense:
"expense_images"
case .payment:
"payment_images"
}
}
}
Expand All @@ -40,10 +43,10 @@ public class StorageManager: ObservableObject {

// Retrieve the download URL asynchronously
let imageUrl = try await storageRef.downloadURL().absoluteString
LogD("StorageManager: Image successfully uploaded to Firebase!")
LogD("StorageManager: \(#function) Image successfully uploaded to Firebase.")
return imageUrl
} catch {
LogE("StorageManager: \(#function) Failed: \(error.localizedDescription)")
LogE("StorageManager: \(#function) Failed to upload image: \(error).")
throw error
}
}
Expand All @@ -59,8 +62,9 @@ public class StorageManager: ObservableObject {
do {
let storageRef = storage.reference(forURL: imageUrl)
try await storageRef.delete()
LogD("StorageManager: \(#function) Image deleted successfully.")
} catch {
LogE("StorageManager: \(#function) Failed: \(error)")
LogE("StorageManager: \(#function) Failed to delete image: \(error).")
throw error
}
}
Expand Down
Loading

0 comments on commit 9f9d96d

Please sign in to comment.