Skip to content

Commit

Permalink
Update Storage iOS Sample. (#1363)
Browse files Browse the repository at this point in the history
* Update Storage iOS Sample.
  • Loading branch information
granluo authored Apr 1, 2022
1 parent 971254d commit 291ce88
Show file tree
Hide file tree
Showing 35 changed files with 1,232 additions and 27 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/storage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
runs-on: macOS-latest
env:
SPM: false
LEGACY: false
LEGACY: true
OS: iOS
DEVICE: iPhone 11
TEST: true
Expand All @@ -37,11 +37,12 @@ jobs:
uses: actions/checkout@master
- name: Setup
run: |
cd storage
cd storage/LegacyStorageQuickstart
gem install bundler
bundle install
gem install xcpretty
bundle exec pod install --repo-update
cd ..
../scripts/install_prereqs/storage.sh
- name: Build ObjC
run: ./scripts/test.sh
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Pods/
xcuserdata/
*.xcworkspace/
GoogleService-Info.plist
*GoogleService-Info.plist
Secrets
Secrets.tar

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
PODS:
- FirebaseAuth (8.12.0):
- FirebaseAuth (8.13.0):
- FirebaseCore (~> 8.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/Environment (~> 7.7)
- GTMSessionFetcher/Core (~> 1.5)
- FirebaseCore (8.12.1):
- FirebaseCore (8.13.0):
- FirebaseCoreDiagnostics (~> 8.0)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Logger (~> 7.7)
- FirebaseCoreDiagnostics (8.12.0):
- FirebaseCoreDiagnostics (8.13.0):
- GoogleDataTransport (~> 9.1)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Logger (~> 7.7)
- nanopb (~> 2.30908.0)
- FirebaseStorage (8.12.0):
- FirebaseStorage (8.13.0):
- FirebaseCore (~> 8.0)
- GTMSessionFetcher/Core (~> 1.5)
- FirebaseStorageSwift (8.12.0-beta):
- FirebaseStorageSwift (8.13.0-beta):
- FirebaseStorage (~> 8.0)
- GoogleDataTransport (9.1.2):
- GoogleUtilities/Environment (~> 7.2)
Expand Down Expand Up @@ -64,11 +64,11 @@ SPEC REPOS:
- PromisesObjC

SPEC CHECKSUMS:
FirebaseAuth: 5250d7bdba35e57cc34ec7ddc525f82b2757f2a0
FirebaseCore: 8138de860a90ca7eec5e324da5788fb0ebf1d93c
FirebaseCoreDiagnostics: 3b40dfadef5b90433a60ae01f01e90fe87aa76aa
FirebaseStorage: 4b75458c35d8b728e4c1fc1371942997456ab299
FirebaseStorageSwift: 895dd37afca82ca52ebfc4ceda2efcacfe7c38e0
FirebaseAuth: ee43cf9474641c673a3a215ac92ab99e5630620c
FirebaseCore: c7e3fa30492e50ccdeef280bf0d5584af38da3e1
FirebaseCoreDiagnostics: c2836d254a8f0bbb4121ff18f2c2ea39d118fd08
FirebaseStorage: 0f115042c1596f5df5a80b67cf414d8f028ccddd
FirebaseStorageSwift: 1762022e0ece4a3ada769f414474497ddad5caee
GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
GTMSessionFetcher: 43748f93435c2aa068b1cbe39655aaf600652e91
Expand Down
File renamed without changes.

Large diffs are not rendered by default.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
252 changes: 252 additions & 0 deletions storage/StorageExample/Shared/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
//
// Copyright (c) 2022 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI
import FirebaseAuth
import FirebaseStorage
import FirebaseStorageSwift

struct ContentView: View {
@EnvironmentObject var viewModel: ViewModel
@State private var authenticated: Bool = true
private var storage = Storage.storage()
private var imageURL: URL = FileManager.default.temporaryDirectory
.appendingPathComponent("tempImage.jpeg")

var body: some View {
ZStack {
VStack {
if let image = viewModel.image {
image
.resizable()
.scaledToFit()
.frame(minWidth: 300, maxHeight: 200)
.cornerRadius(16)

} else {
Image(systemName: "photo.fill")
.resizable()
.scaledToFit()
.opacity(0.6)
.frame(width: 300, height: 200, alignment: .top)
.cornerRadius(16)
.padding(.horizontal)
}
Button("Photo") {
viewModel.showingImagePicker = true
}
.buttonStyle(OrangeButton())
.disabled(!authenticated)
if viewModel.image != nil {
Button("Upload from Data") {
uploadFromData()
}
.buttonStyle(OrangeButton())
}

if viewModel.image != nil, FileManager.default.fileExists(atPath: imageURL.path) {
Button("Upload from URL") {
uploadFromALocalFile()
}
.buttonStyle(OrangeButton())
}
if viewModel.downloadPicButtonEnabled {
Button("Download") {
Task {
await downloadImage()
}
}
.buttonStyle(OrangeButton())
}
}
.sheet(isPresented: $viewModel.showingImagePicker) {
ImagePicker(image: $viewModel.inputImage, imageURL: imageURL)
}
.sheet(isPresented: $viewModel.downloadDone) {
if let image = viewModel.downloadedImage {
image
.resizable()
.scaledToFit()
.frame(minWidth: 0, maxWidth: .infinity)
}
}
.onChange(of: viewModel.inputImage) { _ in
loadImage()
}
.task {
await signInAnonymously()
}
.alert("Error", isPresented: $viewModel.errorFound) {
Text(viewModel.errInfo.debugDescription)
Button("ok") {}
}
.alert("Image was uploaded", isPresented: $viewModel.fileUploaded) {
Button("ok") {}
Button("Link") {
if let url = viewModel.fileDownloadURL {
print("downloaded url: \(url)")
UIApplication.shared.open(url)
}
}
}

if viewModel.isLoading {
LoadingView()
}
}
}

func loadImage() {
guard let inputImage = viewModel.inputImage else {
return
}
viewModel.image = Image(uiImage: inputImage)
viewModel.showingImagePicker = false
}

func uploadFromALocalFile() {
let filePath = Auth.auth().currentUser!.uid +
"/\(Int(Date.timeIntervalSinceReferenceDate * 1000))/\(imageURL.lastPathComponent)"
let storageRef = storage.reference(withPath: filePath)

viewModel.isLoading = true
storageRef.putFile(from: imageURL, metadata: nil) { metadata, error in
guard let _ = metadata else {
// Uh-oh, an error occurred!
viewModel.errorFound = true
viewModel.errInfo = error
return
}

viewModel.isLoading = false
// You can also access to download URL after upload.
fetchDownloadURL(storageRef, storagePath: filePath)
}
}

func uploadFromData() {
guard let imageData = viewModel.inputImage?.jpeg else {
print("The image from url \(imageURL.path) cannot be transferred to data.")
return
}
let filePath = Auth.auth().currentUser!.uid +
"/\(Int(Date.timeIntervalSinceReferenceDate * 1000))/fromData/\(imageURL.lastPathComponent)"
let storageRef = storage.reference(withPath: filePath)

viewModel.isLoading = true
storageRef.putData(imageData, metadata: nil) { metadata, error in
guard let _ = metadata else {
// Uh-oh, an error occurred!
viewModel.errorFound = true
viewModel.errInfo = error
return
}
viewModel.isLoading = false
// You can also access to download URL after upload.
fetchDownloadURL(storageRef, storagePath: filePath)
}
}

func fetchDownloadURL(_ storageRef: StorageReference, storagePath: String) {
storageRef.downloadURL { url, error in

guard let downloadURL = url else {
print("Error getting download URL: \(error.debugDescription)")
viewModel.errorFound = true
viewModel.errInfo = error
return
}
viewModel.remoteStoragePath = storagePath
viewModel.downloadPicButtonEnabled = true
viewModel.fileUploaded = true
viewModel.fileDownloadURL = downloadURL
}
}

func downloadImage() async {
// Create a reference to the file you want to download
let storageRef = Storage.storage().reference()

let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let filePath = "file:\(documentsDirectory)/myimage.jpg"
guard let fileURL = URL(string: filePath) else { return }
guard let storagePath = viewModel.remoteStoragePath else {
return
}

viewModel.isLoading = true
do {
let imageURL = try await storageRef.child(storagePath).writeAsync(toFile: fileURL)
viewModel.downloadDone = true
viewModel.downloadedImage = Image(uiImage: UIImage(contentsOfFile: imageURL.path)!)
} catch {
viewModel.errorFound = true
viewModel.errInfo = error
}
viewModel.isLoading = false
}

func signInAnonymously() async {
// Using Cloud Storage for Firebase requires the user be authenticated. Here we are using
// anonymous authentication.
if Auth.auth().currentUser == nil {
do {
try await Auth.auth().signInAnonymously()
authenticated = true
} catch {
viewModel.errorFound = true
viewModel.errInfo = error
authenticated = false
}
}
}
}

struct OrangeButton: ButtonStyle {
@Environment(\.isEnabled) private var isEnabled: Bool

func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.background(isEnabled ? Color.orange : Color.orange.opacity(0.5))
.foregroundColor(.white)
.clipShape(RoundedRectangle(cornerRadius: 16.0))
}
}

extension UIImage {
var jpeg: Data? { jpegData(compressionQuality: 1) }
}

struct LoadingView: View {
var body: some View {
ZStack {
Color(.systemBackground)
.ignoresSafeArea()
.opacity(0.5)
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .orange))
.scaleEffect(3)
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Loading

0 comments on commit 291ce88

Please sign in to comment.