// // DocumentView.swift // Browse // // Created by Javier Cicchelli on 16/12/2022. // Copyright © 2022 Röck+Cöde. All rights reserved. // import DataModels import KeychainStorage import SwiftUI struct DocumentView: View { // MARK: Environments @Environment(\.dismiss) private var dismiss // MARK: Storages @KeychainStorage(key: .KeychainStorage.account) private var account: Account? // MARK: States @State private var status: ViewStatus = .loading @State private var loadedData: Data? @State private var showDownloadFile: Bool = false private let getData = GetDataUseCase() // MARK: Properties let document: Document let login: ActionClosure // MARK: Body var body: some View { content .navigationTitle(document.name) .navigationBarTitleDisplayMode(.inline) .toolbar { DocumentToolbar(disabled: isToolbarDisabled) { showDownloadFile = true } } .sheet(isPresented: $showDownloadFile) { DownloadView( id: document.id, name: document.name, data: loadedData ) { // downloaded closure. } } .task { await loadDataIfPossible() } } } // MARK: - UI private extension DocumentView { var isToolbarDisabled: Bool { loadedData == nil } @ViewBuilder var content: some View { switch status { case .noCredentials: MessageView( type: .noCredentials, action: login ) case .notSupported: MessageView(type: .notSupported) { dismiss() } case .loading: LoadingView() case .loaded: Image(uiImage: imageFromData) .resizable() .scaledToFit() case .empty: EmptyView() case .error: MessageView(type: .error) { Task { await loadDataIfPossible() } } } } } // MARK: - Helpers private extension DocumentView { // MARK: Computed var supportedContentTypes: [String] { [.ContentType.jpeg, .ContentType.png] } var imageFromData: UIImage { guard let loadedData, let image = UIImage(data: loadedData) else { return .init() } return image } // MARK: Functions func loadDataIfPossible() async { guard supportedContentTypes.contains(document.contentType) else { status = .notSupported return } guard let account else { status = .noCredentials return } do { status = .loading let data = try await getData( id: document.id, username: account.username, password: account.password ) if data.isEmpty { status = .error } else { loadedData = data status = .loaded } } catch { status = .error } } } // MARK: - String+Constants private extension String { enum ContentType { static let jpeg = "image/jpeg" static let png = "image/png" } } // MARK: - Previews struct DocumentView_Previews: PreviewProvider { static var previews: some View { DocumentView(document: .init( id: "1234567890", name: "Some document name goes in here...", contentType: "some content type", size: .random(in: 1 ... 100), lastModifiedAt: .now )) { // login closure. } } }