Adding Storage Functionalities
The page provides instructions on how to add storage/vult functionalities to the app.
Storage Directories
The following directories lies inside the xcode project. Here is the xcode screenshot for example:
Description for the directories and files are provided below:
--Vult(directory)
--App(directory)
--AllocationDetailsView.swift
--VultHome.swift
--Model(directory)
--Allocations.swift
--File.swift
--View(directory)
--AllocationActionStack.swift
--AllocationDetailsBlock.swift
--FilesTable.swift
--ZCNProgressStyle.swift
--ViewModel(directory)
--VultViewModel.swift
Describing Code in Directories
Vult/App/VultHome.swift
//
// VultHome.swift
// ZusExample
//
// Created by Aaryan Kothari on 02/01/23.
//
import SwiftUI
import PhotosUI
struct VultHome: View {
@EnvironmentObject var vultVM: VultViewModel
var body: some View {
GeometryReader { gr in
VStack(alignment: .leading) {
AllocationDetailsBlock()
AllocationActionStack()
FilesTable()
NavigationLink(destination: PreviewController(files: vultVM.files,file: vultVM.selectedFile).navigationTitle(Text(vultVM.selectedFile?.name ?? "")) .navigationBarTitleDisplayMode(.inline).navigationDocument(vultVM.selectedFile?.localThumbnailPath ?? URL(fileURLWithPath: ""))
,isActive: $vultVM.openFile) {
EmptyView()
}
}
.padding(22)
}
.onAppear(perform: vultVM.listDir)
.navigationTitle(Text("Vult"))
.navigationBarTitleDisplayMode(.large)
.background(Color.gray.opacity(0.1))
.sheet(isPresented: $vultVM.presentAllocationDetails) { AllocationDetailsView(allocation: vultVM.allocation) }
.fileImporter(isPresented: $vultVM.presentDocumentPicker, allowedContentTypes: [.image,.pdf,.audio],onCompletion: vultVM.uploadDocument)
.onChange(of: vultVM.selectedPhoto, perform: vultVM.uploadImage)
.environmentObject(vultVM)
}
}
struct VultHome_Previews: PreviewProvider {
static var previews: some View {
let vm : VultViewModel = {
let vm = VultViewModel()
vm.files = [File(name: "IMG_001.PNG", mimetype: "", path: "", lookupHash: "", type: "", size: 8378378399, numBlocks: 0, actualSize: 0, actualNumBlocks: 0, encryptionKey: "", createdAt: 0.0, updatedAt: 0.0, completedBytes: 0)]
return vm
}()
VultHome()
.environmentObject(vm)
}
}
Describing Code:
Line 8
import SwiftUI
gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.Line 9
import PhotosUI
framework for displaying a photo picker or choose photo from directory . Before using it, you have to first import the framework:Line 10 defines a VultHome structure that helps us build the UI of your Vult(Storage functionalities) code.
Line 11 Defines a Environment Object
vultVM
in VultHome structure for sharing data between many views in your app.@EnvironmentObject
property wrapper ensures views automatically stay updated when that data changes.Line 14 defines the variable
body
for holding the main view of VultHome screen.Line 15 utilizes GeometryReader from SwiftUI library imported above to calculate screen position and size information .
Line 15 builds app layouts with stack views. Individually,
VStack
positions them in a vertical line.Line 17 calls AllocationDetailsBlock() function in AllocationDetailsBlock.swift
Line 19 calls AllocationActionStack() function in AllocationActionStack.swift
Line21 calls FilesTable() function in FilesTable.swift
Line 23 implements a NavigationLink to push a view programmatically to navigation controller in this case user opens a file or navigates.
Line 25 calls an EmptyView() that doesn’t contain any content.
Line 28 adds a layer of padding to NavigationLink view defined at line 23 and 24.
Line 30 adds an action to list directories before the view in code snippet appears.
Line 31 defines title for the navigationLink which is Vult.
Line 32 configures the title display mode for the view to be large.
Line 33 defines a background in gray color.
Line 34 utilize Sheets in SwiftUI to present views(AllocationDetails) that partly cover the underlying screen.
Line 35 utilize fileImporter to presents a system interface for allowing the user to import multiple files and then call uploadDocument when the upload is completed.
Line 36 adds a modifier for the view and fires an action(uploading image) when the value changes (uploadImage).
Line 37 passes
vultVM
object as @EnvironmentObject* property wrapper to create and update views automatically.Line 41 defines a Previewprovider type that produces view for the VultHome structure
Line 44 creates a variable vm to hold VultViewModel instance and access it methods
Line 45 specifies a file schema for upload
VultHome instance is passed as a view to be produced with environment object sharing data between VultViewModel Instance.
Vult/Model/Allocations.swift
//
// Allocation.swift
// ZusExample
//
// Created by Aaryan Kothari on 02/01/23.
//
import Foundation
typealias Allocations = [Allocation]
struct Allocation: Codable {
var id,name: String?
var dataShards, parityShards, expirationDate: Int?
var size, usedSize, numOfWrites, numOfReads, totalChallenges: Int?
var numOpenChallenges, numSuccessChallenges, numFailedChallenges: Int?
var latestClosedChallenge: String?
enum CodingKeys: String, CodingKey {
case id
case name
case dataShards = "data_shards"
case parityShards = "parity_shards"
case size
case expirationDate = "expiration_date"
case usedSize = "used_size"
case numOfWrites = "num_of_writes"
case numOfReads = "num_of_reads"
case totalChallenges = "total_challenges"
case numOpenChallenges = "num_open_challenges"
case numSuccessChallenges = "num_success_challenges"
case numFailedChallenges = "num_failed_challenges"
case latestClosedChallenge = "latest_closed_challenge"
}
mutating func addStats(_ model: Self) {
self.usedSize = model.usedSize
self.numOfWrites = model.numOfWrites
self.numOfReads = model.numOfReads
self.totalChallenges = model.totalChallenges
self.numOpenChallenges = model.numOpenChallenges
self.numSuccessChallenges = model.numSuccessChallenges
self.numFailedChallenges = model.numFailedChallenges
self.latestClosedChallenge = model.latestClosedChallenge
}
mutating func addSize(_ size: Int) {
self.usedSize = (self.usedSize ?? 0) + size
}
var allocationFraction: Double {
return Double(usedSize ?? 0)/Double(size ?? 1)
}
var allocationPercentage: Int {
return ((usedSize ?? 0)/(size ?? 1)) * 100
}
var defaultName: String {
if let name = self.name, !name.isEmpty {
return name
} else {
return "Allocation"
}
}
}
Describing Code:
Line 8
import Foundation
is required to provide a base layer of functionality for apps and frameworks, including data storage and persistence, text processing, date and time calculations, sorting and filtering, and networking.Line 10 makes use of a type alias allows you to provide a new name(Allocations in this case) for an existing data type (Allocation )into your program. The aliased name can be used instead of the existing type throughout the program.
Line 12 defines Allocation structure and the following fields :
var id : Allocation ID
var name : Allocation name
var dataShards : Holding data shards value, effects upload and download speeds
var parityShards: Holding parity shards value , effects availability
var expirationDate: Holding Allocation Expiry date
var used Size: Holds Used space in bytes inAllocation
var numofWrites : Holds value for number of times data written to allocation.
var numofReads : Holds value for number of times data read from allocations.
var totalChallenges : Holds Total Challenges for blobbers(opened+closed+successful+failed)
var numOpenChallenges : Holds value for number of open challenges blobber has to complete
var numSuccessChallenges : Holds value for number of challenges blobber successfully completed.
var numFailedChallenges : Holds value for number of failed challenges by blobbers.
var latestClosedChallenge :Holds value for latest completed challenge by blobber.
Line 19 to 34 created enumerations and cases for all the fields defined in Allocation Structure. A particular case can be executed depending upon the value of switch statement.
Line 36 to 45 defines a addStats function that's been marked as mutating and can change any property within its enclosing value(the values in this case that can be changed are from line 37 to 44)
Line 47 defines a mutating addSize function to modify the value of instance variable type allocation
size
.Line 51 defines a allocationFraction variable which returns the fraction of allocation used.
Line 55 defines an allocationPercentage variable which returns allocation usedsize in terms of percentage.
Line 59 defines a variable defaultName which returns Allocation name retrieved from instance variable. In case the instance name field is empty return "Allocation" as String.
Vult/Model/File.swift
//
// File.swift
// ZusExample
//
// Created by Aaryan Kothari on 02/01/23.
//
import Foundation
struct Directory: Codable {
let list: [File]
}
typealias Files = [File]
struct File: Codable, Identifiable, Equatable {
var id: String {
return status.rawValue + completedBytes.stringValue
}
var name : String = ""
var mimetype: String = ""
var path: String = ""
var lookupHash: String = ""
var type: String = ""
var size: Int = 0
var numBlocks : Int? = 0
var actualSize : Int? = 0
var actualNumBlocks : Int? = 0
var encryptionKey: String? = ""
var createdAt: Double = 0
var updatedAt: Double = 0
enum CodingKeys: String, CodingKey {
case name = "name"
case mimetype = "mimetype"
case path = "path"
case lookupHash = "lookup_hash"
case type = "type"
case size = "size"
case numBlocks = "num_blocks"
case encryptionKey = "encryption_key"
case actualSize = "actual_size"
case actualNumBlocks = "actual_num_blocks"
case createdAt = "created_at"
case updatedAt = "updated_at"
}
internal init(name: String = "", mimetype: String = "", path: String = "", lookupHash: String = "", type: String = "", size: Int = 0, numBlocks: Int? = 0, actualSize: Int? = 0, actualNumBlocks: Int? = 0, encryptionKey: String? = "", createdAt: Double = 0, updatedAt: Double = 0, completedBytes: Int = 0) {
self.name = name
self.mimetype = mimetype
self.path = path
self.lookupHash = lookupHash
self.type = type
self.size = size
self.numBlocks = numBlocks
self.actualSize = actualSize
self.actualNumBlocks = actualNumBlocks
self.encryptionKey = encryptionKey
self.createdAt = createdAt
self.updatedAt = updatedAt
self.completedBytes = completedBytes
}
var localThumbnailPath: URL {
return Utils.downloadedThumbnailPath.appendingPathComponent(self.path)
}
var localUploadPath: URL {
return Utils.uploadPath.appendingPathComponent(self.path)
}
var localFilePath: URL {
return Utils.downloadPath.appendingPathComponent(self.path)
}
var isDownloaded: Bool {
return FileManager.default.fileExists(atPath: localFilePath.path)
}
var isUploaded: Bool = true
var completedBytes: Int = 0
enum FileStatus {
case error
case progress
case completed
}
var fileSize: String {
switch status {
case .completed: return size.formattedByteCount
case .progress: return "\(completedBytes/size) %"
case .error: return "failed"
}
}
var fileDownloadPercent: String {
return "\(completedBytes/size) %"
}
var status: FileStatus = .completed
}
Describing Code:
Line 8
import Foundation
is required to provide a base layer of functionality for apps and frameworks, including data storage and persistence, text processing, date and time calculations, sorting and filtering, and networking.Line 10 defines directory strucure for files stored as list.
Line 14 makes use of a type alias allows you to provide a new name(Files in this case) for an existing data type (File )into your program. The aliased name can be used instead of the existing type throughout the program.
Line 16 defines File structure and the following fields :
var id : File ID .
var name : File name
var mimetype : File MIME Type
var path: File path
var lookuphash: Holding File LookupHash
var type : Holding File Type
var size : Holding value for File Size
var numBlocks : Holding value file in terms of number of blocks .
var actualSize : Holding Actual File Size.
var actualNumBlocks : Holding value for file in terms of actual file blocks.
var encryption : Holds value for file encrpytion Key.
var createdAt : Holding value for when file is created
var updatedAt :Holding value for when file is updated.
Line 36 to 65 created enumerations and cases for all the fields defined in File Structure. A particular case can be executed depending upon the value of particular statement evaluation in the program.
Line 67 to 81 creates the following variable for handling various file operations.
localThumbnailPath: Returns thumbnail path for the file.
localUploadPath: Returns local path for the uploaded file
localFilePath : Returns Local path for the file.
isDownloaded : Returns whether the downloaded file exists at specified path.
Boolean isUploaded : Returns boolean value true when the file is uploaded
completedBytes : Returns number of completed bytes for file download.
Line 87 define enum and cases for file status.
Line 91 defines variable fileSize and functionalities for cases created for file status
In case of completed file status return the file size in bytes.
In case of file status in progress return number of completed bytes divide by size in percentage.
In case of file status in error ,return failed status.
Line 93 to 99 defines variable fileDownloadPercent which returns downloaded file progress in percent.
Vult/View/AllocationActionStack.swift
//
// AllocationActionStack.swift
// ZusExample
//
// Created by Aaryan Kothari on 03/01/23.
//
import SwiftUI
import PhotosUI
struct AllocationActionStack: View {
@EnvironmentObject var vultVM: VultViewModel
@Environment(\.colorScheme) var colorScheme
var body: some View {
HStack(spacing:10) {
PhotosPicker(
selection: $vultVM.selectedPhoto,
matching: .images,
photoLibrary: .shared()) {
WalletActionBlock(icon: "photo",title: "Upload Image")
}
WalletActionBlock(icon: "document",title: "Upload Document")
.onTapGesture {
vultVM.presentDocumentPicker = true
}
}
.aspectRatio(3.2, contentMode: .fit)
.shadow(color: .init(white: colorScheme == .dark ? 0.05 : 0.95), radius: 100, x: 0, y: 0)
}
}
struct AllocationActionStack_Previews: PreviewProvider {
static var previews: some View {
AllocationActionStack()
.environmentObject(VultViewModel())
.background(Color.gray.opacity(0.1))
.previewLayout(.sizeThatFits)
}
}
struct WalletActionBlock: View {
var icon: String
var title: String
var body: some View {
GeometryReader { gr in
VStack(alignment: .center) {
Image(icon)
.resizable()
.aspectRatio(1, contentMode: .fit)
.frame(width: gr.size.width/2)
Text(title)
}
.frame(maxWidth: .infinity,maxHeight: .infinity)
.font(.system(size: 13, weight: .semibold))
.foregroundColor(.primary)
.padding()
.background(Color.tertiarySystemBackground)
.cornerRadius(12)
}
}
}
Describing Code :
Line 8
import SwiftUI
gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.Line 9
import PhotosUI
framework for displaying a photo picker or choose photo from directory . Before using it, you have to first import the frameworkLine 11 defines a AllocationAction structure that helps us manage view for the Allocation functionalities in Vult code.
Line 12 defines a Environment Object
vultVM
in pointing to VultViewModel structure for sharing data between views in your app.@EnvironmentObject
property wrapper ensures views automatically stay updated when that data changes.Line 13 creates variable that holds value for possible color schemes, corresponding to the light and dark appearances.
Line 15 to 32 builds app layouts with stack views. Individually,
HStack
positions them in a horizontal line.Line 17 to 20 implements a view that displays a Photos picker for choosing assets from the photo library.
Line 21 appends the photopicker with a WalletActionBlock.
Line 24 to 27 creates another WalletActionBlock named Upload Document which presents a document picker for choosing documents from library when ontap gesture is detected.
Line 34 to 40 defines a Previewprovider type that produces view for the AllocationActionStack structure .An AllocationActionStack instance is passed as a view to be produced.
Line 43 to 63 defines view for the WalletActionBlock utilized by AllocationActionBlock
Line 44 and 45 defines the following variables for WalletActionBlock.
A variable named
icon
for holding photo.A variable named
title
for naming particular action functionality uploading documents or photos.
Line 48 defines a GeometryReader from SwiftUI library imported above to calculate screen position and size information.
Line 50 to 54 builds app layouts with stack views. Individually,
VStack
positions them in a vertical line .
Vult/View/AllocationDetailsBlock.swift
//
// AllocationDetailsBlock.swift
// ZusExample
//
// Created by Aaryan Kothari on 03/01/23.
//
import SwiftUI
struct AllocationDetailsBlock: View {
@EnvironmentObject var vultVM: VultViewModel
@Environment(\.colorScheme) var colorScheme
var body: some View {
HStack(spacing:20) {
VStack(alignment: .leading) {
Text(vultVM.allocation.defaultName)
.font(.system(size: 14, weight: .semibold))
Text(vultVM.allocation.expirationDate?.formattedUNIX ?? "")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(.gray)
}
VStack(alignment: .leading) {
ProgressView(value: vultVM.allocation.allocationFraction)
.progressViewStyle(ZCNProgressStyle())
.frame(height: 10)
Text("\(vultVM.allocation.usedSize?.formattedByteCount ?? "") used of \(vultVM.allocation.size?.formattedByteCount ?? "") (\(vultVM.allocation.allocationPercentage)%)")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(.gray)
.lineLimit(1)
}
}
.padding(.horizontal,16)
.padding(.vertical,12)
.background(Color.tertiarySystemBackground)
.cornerRadius(12)
.shadow(color: .init(white: colorScheme == .dark ? 0.25 : 0.75), radius: 100, x: 0, y: 0)
}
}
struct AllocationDetailsBlock_Previews: PreviewProvider {
static var previews: some View {
AllocationDetailsBlock()
.environmentObject(VultViewModel())
.previewLayout(.sizeThatFits)
}
}
Describing Code :
Line 8
import SwiftUI
gives access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.Line 10 defines a AllocationDetailsBlock structure that defines how allocation details should be displayed in the App.
Line 15 to 22 builds app layouts with stack views. Individually,
VStack
positions them in a vertical line(top to bottom) .HStack, a horizontal stack, which shows views in a left-to-right list.Allocation Name and Expiration Date is listed as a textView.(Line 16 to 21)
Then in another Vertical Stack(VStack) a progress view and text is defined describing how much allocation space is used by files (Line 24 to 32)
Line 36 to 40 defines padding,background and shadow for Vertically and Horizontally Stacked Views.
Line 44 to 44 defines a Previewprovider type that produces view for the AllocationDetailsBlock structure .An AllocationDetailsBlock() instance is passed with VultViewModel instance as an environment object to share data during view production .
Vult/View/FilesTable.swift
//
// FilesTable.swift
// ZusExample
//
// Created by Aaryan Kothari on 03/01/23.
//
import SwiftUI
struct FilesTable: View {
@EnvironmentObject var vultVM: VultViewModel
@State var previewFile:Bool = false
var body: some View {
VStack(alignment: .leading) {
Text("All Files").bold()
ScrollView(showsIndicators: false) {
ForEach(vultVM.files,id:\.id) { file in
FileRow(file: file)
.id(file.id)
.onTapGesture {
if file.isDownloaded {
self.vultVM.openFile = true
self.vultVM.selectedFile = file
} else if file.isUploaded {
vultVM.downloadImage(file: file)
}
}
}
}
}
}
}
struct FilesTable_Previews: PreviewProvider {
static var previews: some View {
let vm : VultViewModel = {
let vm = VultViewModel()
vm.files = [File(name: "IMG_001.PNG", mimetype: "", path: "", lookupHash: "", type: "", size: 8378378399, numBlocks: 0, actualSize: 0, actualNumBlocks: 0, encryptionKey: "", createdAt: 0.0, updatedAt: 0.0, completedBytes: 0)]
return vm
}()
FilesTable()
.environmentObject(vm)
}
}
struct FileRow: View {
@State var file: File
var body: some View {
HStack(spacing: 20) {
if let image = ZCNImage(contentsOfFile: file.localThumbnailPath.path) {
Image(image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(8)
} else {
Image(systemName: "doc.circle.fill")
.resizable()
.symbolRenderingMode(.hierarchical)
.frame(width: 38, height: 38)
.cornerRadius(8)
.foregroundColor(.teal)
}
Text(file.name)
.font(.system(size: 15, weight: .semibold))
.lineLimit(1)
Spacer()
Text(file.fileSize)
.font(.system(size: 14, weight: .semibold))
.foregroundColor(.gray)
if !file.isDownloaded && file.isUploaded {
VStack(alignment: .center,spacing: 3) {
Image(systemName: "arrow.down.to.line.circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 20)
.symbolRenderingMode(file.status == .progress ? .monochrome : .hierarchical)
if file.status == .progress {
Text(file.fileDownloadPercent)
.font(.system(size: 8))
}
}
.foregroundColor(.teal)
}
}
.padding(.vertical,12)
.padding(.horizontal,18)
.background(Color.tertiarySystemBackground)
.cornerRadius(12)
}
}
Describing Code :
Line 8
import SwiftUI
gives access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.Line 10 defines a FilesTable structure that dictates how files uploaded to dStorage should be displayed in the App.
Line 11 defines VultVM variable that holds a VultViewModel object .
@EnvironmentObject
property wrapper ensure views are shared properly across an entire SwiftUI app.Line 12 defines a Boolean for holding state in case when the file is previewed
Line 14 to 33 builds app layouts with stack views. Individually,
VStack
positions them in a vertical line(top to bottom) with a text view titled(All Files) in boldLine 17 implements a scrollable view for all the files on the Allocation
Line 18 to 20 list all the files available in the allocation
Line 21 to 27 defines action in case of tap on a listed file or download button.
Flow: If user downloads the file open the selected file. else if the file is uploaded download the selected or tapped file
Line 35 to 46 defines a Previewprovider type that produces view for the FilesTable structure .A FilesTable() instance is passed with VultViewModel instance as an environment object to share data during view production .
Line 48 to 95 defines a structure that dictates the layout for the listed files
(Line 49) A variable
file
holding a particular file state.(Line 51) HStack, a horizontal stack, which shows views in a left-to-right list with spacing of 20 pexels.
(Line 53 to 56) In a HStack properties for the displayed image are defined(Image has to be resizable with a specified frame and corner radius )
(Line 58 to 63) In case no thumbnail found for a particular image the thumbnail image should have the following properties.
A resizable thumbnail image of teal color with a specified frame and corner radius
(Line 66 to 74 ) A view that displays file name as text and size with display properties
(Line 76 to 89)If the Uploaded files are downloaded display the following symbol..
Line (92 to 95) defines padding,background and radius for Vertically and Horizontally Stacked Views.
Vult/View/ZCNProgressStyle.swift
//
// ZCNProgressStyle.swift
// ZusExample
//
// Created by Aaryan Kothari on 03/01/23.
//
import Foundation
import SwiftUI
struct ZCNProgressStyle: ProgressViewStyle {
var strokeColor = Color.blue
var strokeWidth = 25.0
func makeBody(configuration: Configuration) -> some View {
let fractionCompleted = configuration.fractionCompleted ?? 0
return ZStack {
GeometryReader { gr in
RoundedRectangle(cornerRadius: gr.size.height/2)
.fill(Color.teal.opacity(0.3))
.frame(width: gr.size.width, alignment: .leading)
RoundedRectangle(cornerRadius: gr.size.height/2)
.fill(Color.teal)
.frame(width: gr.size.width * fractionCompleted, alignment: .leading)
}
}
}
}
Describing Code :
Line 11 defines a ZCNProgressStyle structure that dictates the layout for the ZCN progress bar in case of faucet send and recieve.
Line 15 defines function
makeBody
to define how the layout should be for the ZCN progress bar.Line 16 defines a variable that holds ZCN progress in fractions
Line 18 to 25 defines a ZStack, a depth-based stack, which shows views in a back-to-front list defines a rounded rectangle inn which ZCN progress bar in fractions should be displayed.
Vult/ViewModel/VultViewModel.swift
//
// VultViewModel.swift
// ZusExample
//
// Created by Aaryan Kothari on 28/12/22.
//
import Foundation
import Zcncore
import Combine
import _PhotosUI_SwiftUI
class VultViewModel: NSObject, ObservableObject {
static var zboxAllocationHandle : ZboxAllocation? = nil
@Published var allocation: Allocation = Allocation()
@Published var presentAllocationDetails: Bool = false
@Published var presentDocumentPicker: Bool = false
@Published var files: Files = []
@Published var selectedPhoto: PhotosPickerItem? = nil
@Published var selectedFile: File? = nil
@Published var openFile: Bool = false
override init() {
super.init()
VultViewModel.zboxAllocationHandle = try? ZcncoreManager.zboxStorageSDKHandle?.getAllocation(Utils.get(key: .allocationID) as? String)
self.getAllocation()
}
func getAllocation() {
DispatchQueue.global().async {
do {
let decoder = JSONDecoder()
guard let zboxAllocationHandle = VultViewModel.zboxAllocationHandle else { return }
var allocation = Allocation()
allocation.id = zboxAllocationHandle.id_
allocation.size = Int(zboxAllocationHandle.size)
allocation.dataShards = zboxAllocationHandle.dataShards
allocation.parityShards = zboxAllocationHandle.parityShards
allocation.name = zboxAllocationHandle.name
allocation.expirationDate = Int(zboxAllocationHandle.expiration)
let allocationStats = zboxAllocationHandle.stats
let allocationStatsData = Data(allocationStats.utf8)
let allocationStatsModel = try decoder.decode(Allocation.self, from: allocationStatsData)
allocation.addStats(allocationStatsModel)
DispatchQueue.main.async {
self.allocation = allocation
}
} catch let error {
print(error)
}
}
}
func uploadImage(selectedPhoto: PhotosPickerItem?) {
Task {
do {
guard let newItem = selectedPhoto else { return }
let name = PHAsset.fetchAssets(withLocalIdentifiers: [newItem.itemIdentifier!], options: nil).firstObject?.value(forKey: "filename") as? String ?? ""
if let data = try await newItem.loadTransferable(type: Data.self) {
try uploadFile(data: data, name: name)
}
} catch let error {
print(error.localizedDescription)
}
}
}
func uploadDocument(result: Result<URL, Error>) {
do {
let url = try result.get()
guard url.startAccessingSecurityScopedResource() else { return }
let name = url.lastPathComponent
let data = try Data(contentsOf: url)
try uploadFile(data: data, name: name)
} catch let error {
print(error.localizedDescription)
}
}
func uploadFile(data: Data, name: String) throws {
var localPath = Utils.uploadPath.appendingPathComponent(name)
var thumbnailPath = Utils.downloadedThumbnailPath.appendingPathComponent(name)
if let image = ZCNImage(data: data) {
let pngData = image.pngData()
try pngData?.write(to: localPath,options: .atomic)
let thumbnailData = image.jpegData(compressionQuality: 0.1)
try thumbnailData?.write(to: thumbnailPath)
} else {
try data.write(to: localPath,options: .atomic)
}
try VultViewModel.zboxAllocationHandle?.uploadFile(withThumbnail: Utils.tempPath(),
localPath: localPath.path,
remotePath: "/\(name)",
fileAttrs: nil,
thumbnailpath: thumbnailPath.path,
statusCb: self)
}
func downloadImage(file: File) {
do {
try VultViewModel.zboxAllocationHandle?.downloadFile(file.path,
localPath: file.localFilePath.path,
statusCb: self)
} catch let error {
print(error.localizedDescription)
}
}
func listDir() {
DispatchQueue.global().async {
do {
guard let allocation = VultViewModel.zboxAllocationHandle else { return }
var error: NSError? = nil
let jsonStr = allocation.listDir("/"