-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFirebaseManager.swift
More file actions
141 lines (119 loc) · 5.39 KB
/
Copy pathFirebaseManager.swift
File metadata and controls
141 lines (119 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// This source file is part of the Stanford 360 based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
//
// SPDX-License-Identifier: MIT
//
import FirebaseFirestore
import FirebaseStorage
import Foundation
extension Stanford360Standard {
func storeMeal(_ meal: Meal/*, selectedImage: UIImage?*/) async {
guard let mealID = meal.id else {
print("❌ Meal ID is nil.")
return
}
// store the Meal to Firestore
do {
let docRef = try await configuration.userDocumentReference
try await docRef.collection("meals").document(mealID).setData(from: meal)
print("✅ Meal saved to Firestore with ID: \(mealID)")
} catch {
print("❌ Error writing meal to Firestore: \(error)")
}
}
// periphery:ignore
func deleteMealByID(byID id: String) async {
do {
let userDocRef = try await configuration.userDocumentReference
try await userDocRef
.collection("meals")
.document(id)
.delete()
print("✅ Successfully deleted meal with ID: \(id) from Firebase and local data.")
} catch {
print("❌ Error deleting meal from Firebase: \(error)")
}
}
func uploadImageToFirebase(_ image: UIImage, imageName: String) async -> String? {
// Resize image before uploading
let resizedImage = resizeImageIfNeeded(image, maxDimension: 1200)
// Compress with appropriate quality
guard let imageData = resizedImage.jpegData(compressionQuality: 0.7)
else {
return nil
}
let uniqueImageName = "\(UUID().uuidString)_\(imageName)"
do {
let storageRef = try await configuration.userBucketReference.child("\(uniqueImageName).jpg")
// Set up upload metadata
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
// Determine if we should use chunked upload based on image size
// Threshold of 1MB for advanced progress tracking
let useProgressTracking = imageData.count > 1_000_000
if useProgressTracking {
// Use progress-tracked upload for larger images
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
let uploadTask = storageRef.putData(imageData, metadata: metadata)
// Add progress observer
uploadTask.observe(.progress) { snapshot in
if let progress = snapshot.progress {
let percentComplete = Double(progress.completedUnitCount) / Double(progress.totalUnitCount) * 100
print("Upload progress: \(percentComplete)%")
}
}
uploadTask.observe(.success) { _ in
continuation.resume(returning: ())
}
uploadTask.observe(.failure) { snapshot in
if let error = snapshot.error {
continuation.resume(throwing: error)
}
}
}
} else {
// Use simple upload for smaller images
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
storageRef.putData(imageData, metadata: metadata) { _, error in
if let error = error {
continuation.resume(throwing: error)
} else {
continuation.resume(returning: ())
}
}
}
}
let downloadURL = try await storageRef.downloadURL()
print("✅ Image successfully uploaded to: \(downloadURL)")
return downloadURL.absoluteString
} catch {
print("❌ Error uploading image: \(error)")
return nil
}
}
// Helper function to resize images
private func resizeImageIfNeeded(_ image: UIImage, maxDimension: CGFloat) -> UIImage {
let originalSize = image.size
// If the image is already smaller than our target size, return the original
if originalSize.width <= maxDimension && originalSize.height <= maxDimension {
return image
}
// Calculate the target size maintaining aspect ratio
let aspectRatio = originalSize.width / originalSize.height
let targetSize: CGSize
if originalSize.width > originalSize.height {
targetSize = CGSize(width: maxDimension, height: maxDimension / aspectRatio)
} else {
targetSize = CGSize(width: maxDimension * aspectRatio, height: maxDimension)
}
// Render the resized image
let renderer = UIGraphicsImageRenderer(size: targetSize)
let resizedImage = renderer.image { _ in
image.draw(in: CGRect(origin: .zero, size: targetSize))
}
return resizedImage
}
}
extension StorageReference: @unchecked @retroactive Sendable {}