48 lines
1.3 KiB
Swift
48 lines
1.3 KiB
Swift
|
|
import Foundation
|
||
|
|
|
||
|
|
struct GalleryItem: Identifiable, Sendable {
|
||
|
|
let id: String
|
||
|
|
let filename: String
|
||
|
|
let creationDate: Date?
|
||
|
|
let duration: TimeInterval? // non-nil for video
|
||
|
|
let fileSize: Int64?
|
||
|
|
let mediaType: MediaType
|
||
|
|
let source: ItemSource
|
||
|
|
|
||
|
|
enum MediaType: Sendable { case photo, video, unknown }
|
||
|
|
|
||
|
|
enum ItemSource: Sendable {
|
||
|
|
case phone(localIdentifier: String)
|
||
|
|
case nas(path: String)
|
||
|
|
case synced(localIdentifier: String, nasPath: String)
|
||
|
|
|
||
|
|
var localIdentifier: String? {
|
||
|
|
switch self { case .phone(let id), .synced(let id, _): id; case .nas: nil }
|
||
|
|
}
|
||
|
|
var nasPath: String? {
|
||
|
|
switch self { case .nas(let p), .synced(_, let p): p; case .phone: nil }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
enum SyncState: Sendable {
|
||
|
|
case phoneOnly // orange — backed up soon
|
||
|
|
case nasOnly // blue — on NAS, not this device
|
||
|
|
case synced // green — confirmed both places
|
||
|
|
}
|
||
|
|
|
||
|
|
var syncState: SyncState {
|
||
|
|
switch source {
|
||
|
|
case .phone: .phoneOnly
|
||
|
|
case .nas: .nasOnly
|
||
|
|
case .synced: .synced
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
struct GallerySection: Identifiable {
|
||
|
|
var id: String // "2026-05-17" or "unknown"
|
||
|
|
var date: Date
|
||
|
|
var title: String
|
||
|
|
var items: [GalleryItem]
|
||
|
|
}
|