Skip to main content

Overview

UploadItem represents a single completed upload in the upload history. It stores metadata about the uploaded file including its name, size, R2 key, upload date, and public URL. The model conforms to Identifiable for SwiftUI list display and Codable for JSON persistence.
Located at: Fiaxe/Models/UploadItem.swift:4

Type Definition

struct UploadItem: Identifiable, Codable, Sendable
A value type that conforms to:
  • Identifiable - For use in SwiftUI lists with stable identity
  • Codable - For JSON serialization to UserDefaults
  • Sendable - For safe passing across actor boundaries

Properties

id

Unique identifier for the upload item.
let id: UUID
id
UUID
Auto-generated UUID for stable identity in SwiftUI lists.

fileName

Original name of the uploaded file.
let fileName: String
fileName
String
The original filename (e.g., "photo.jpg", "document.pdf").

fileSize

Size of the uploaded file in bytes.
let fileSize: Int64
fileSize
Int64
File size in bytes. Used for displaying formatted size to users.

r2Key

The object key used in R2 storage.
let r2Key: String
r2Key
String
The full R2 object key (e.g., "abc12345-photo.jpg", "uploads/2024/document.pdf").

uploadDate

Timestamp when the upload completed.
let uploadDate: Date
uploadDate
Date
The date and time when the upload completed. Automatically set to current time during initialization.
Property NameThe property is named uploadDate, not timestamp. This matches the actual source code implementation.

publicURL

Public URL for accessing the uploaded file.
let publicURL: URL
publicURL
URL
The public URL where the file can be accessed (e.g., custom domain URL or R2 public URL).

Computed Properties

formattedFileSize

Human-readable file size string.
var formattedFileSize: String {
    ByteCountFormatter.string(fromByteCount: fileSize, countStyle: .file)
}
Returns: Formatted string like "2.1 MB", "456 KB", "1.2 GB". Uses Foundation’s ByteCountFormatter for localized, user-friendly formatting.

Initializer

Creates a new upload item with automatic ID and timestamp generation.
init(fileName: String, fileSize: Int64, r2Key: String, publicURL: URL)
fileName
String
required
Original filename of the uploaded file.
fileSize
Int64
required
Size of the file in bytes.
r2Key
String
required
The R2 object key where the file is stored.
publicURL
URL
required
Public URL for accessing the uploaded file.

Implementation Details

// Example from UploadItem.swift:12-19
init(fileName: String, fileSize: Int64, r2Key: String, publicURL: URL) {
    self.id = UUID()
    self.fileName = fileName
    self.fileSize = fileSize
    self.r2Key = r2Key
    self.uploadDate = Date()
    self.publicURL = publicURL
}
The initializer:
  1. Generates a new UUID for the id
  2. Stores the provided parameters
  3. Sets uploadDate to the current date/time

Usage Example

import Foundation

// Create an upload item after successful upload
let uploadItem = UploadItem(
    fileName: "vacation-photo.jpg",
    fileSize: 2_048_576,  // 2 MB
    r2Key: "abc12345-vacation-photo.jpg",
    publicURL: URL(string: "https://pub.example.com/abc12345-vacation-photo.jpg")!
)

print(uploadItem.id)  // UUID: 123e4567-e89b-12d3-a456-426614174000
print(uploadItem.formattedFileSize)  // "2 MB"
print(uploadItem.uploadDate)  // 2024-03-15 12:30:45

SwiftUI List Integration

import SwiftUI

struct UploadHistoryView: View {
    let items: [UploadItem]
    
    var body: some View {
        List(items) { item in
            VStack(alignment: .leading, spacing: 4) {
                Text(item.fileName)
                    .font(.headline)
                
                HStack {
                    Text(item.formattedFileSize)
                    Text("•")
                    Text(item.uploadDate.formatted(date: .abbreviated, time: .shortened))
                }
                .font(.caption)
                .foregroundColor(.secondary)
                
                Text(item.publicURL.absoluteString)
                    .font(.caption2)
                    .foregroundColor(.blue)
                    .lineLimit(1)
            }
        }
    }
}

Adding to History Store

// After successful upload
let fileSize = try FileManager.default.attributesOfItem(
    atPath: fileURL.path
)[.size] as! Int64

let publicURL = credentials.customDomain ?? credentials.endpoint
    .appendingPathComponent(credentials.bucketName)
    .appendingPathComponent(generatedKey)

let uploadItem = UploadItem(
    fileName: fileURL.lastPathComponent,
    fileSize: fileSize,
    r2Key: generatedKey,
    publicURL: publicURL
)

uploadHistoryStore.add(uploadItem)

JSON Encoding

The model automatically encodes to JSON via Codable:
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "fileName": "vacation-photo.jpg",
  "fileSize": 2048576,
  "r2Key": "abc12345-vacation-photo.jpg",
  "uploadDate": "2024-03-15T12:30:45Z",
  "publicURL": "https://pub.example.com/abc12345-vacation-photo.jpg"
}
Used by UploadHistoryStore for persistence.

Sendable Conformance

Thread SafetyThe Sendable conformance allows passing UploadItem across actor boundaries:
Task.detached {
    let item = UploadItem(...)  // Created on background
    await MainActor.run {
        historyStore.add(item)  // Safely passed to main actor
    }
}
All properties are value types or immutable, making this safe.

Identifiable Conformance

The id property satisfies Identifiable for SwiftUI:
List(uploadItems) { item in  // ✓ Works because UploadItem: Identifiable
    UploadHistoryRow(item: item)
}
SwiftUI uses the id to:
  • Track items across updates
  • Animate insertions/deletions
  • Maintain selection state

File Size Formatting Examples

let examples = [
    (bytes: 1_024, formatted: "1 KB"),
    (bytes: 1_048_576, formatted: "1 MB"),
    (bytes: 2_500_000, formatted: "2.4 MB"),
    (bytes: 1_073_741_824, formatted: "1 GB"),
    (bytes: 500, formatted: "500 bytes")
]

for example in examples {
    let item = UploadItem(
        fileName: "test.file",
        fileSize: example.bytes,
        r2Key: "key",
        publicURL: URL(string: "https://example.com")!
    )
    print(item.formattedFileSize)  // Matches example.formatted
}

Design Considerations

UUIDs provide guaranteed uniqueness even if multiple uploads complete in the same millisecond. Timestamps could collide.
The URL may depend on custom domain settings that could change. Storing ensures the URL remains valid even if configuration changes.
Supports files up to 8 exabytes. Int would be limited to 2 GB on some architectures.
Upload history entries represent completed events that shouldn’t change. Immutability prevents accidental modification.