2022-12-16 01:47:44 +01:00
|
|
|
//
|
|
|
|
// 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?
|
2022-12-18 01:08:38 +01:00
|
|
|
@State private var showDownloadFile: Bool = false
|
2022-12-16 01:47:44 +01:00
|
|
|
|
|
|
|
private let getData = GetDataUseCase()
|
|
|
|
|
|
|
|
// MARK: Properties
|
|
|
|
|
|
|
|
let document: Document
|
|
|
|
let login: ActionClosure
|
|
|
|
|
|
|
|
// MARK: Body
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
content
|
|
|
|
.navigationTitle(document.name)
|
|
|
|
.navigationBarTitleDisplayMode(.inline)
|
2022-12-18 01:08:38 +01:00
|
|
|
.toolbar {
|
|
|
|
DocumentToolbar(disabled: isToolbarDisabled) {
|
|
|
|
showDownloadFile = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.sheet(isPresented: $showDownloadFile) {
|
|
|
|
DownloadView(
|
|
|
|
id: document.id,
|
|
|
|
name: document.name,
|
|
|
|
data: loadedData
|
|
|
|
) {
|
|
|
|
// downloaded closure.
|
|
|
|
}
|
|
|
|
}
|
2022-12-16 01:47:44 +01:00
|
|
|
.task {
|
|
|
|
await loadDataIfPossible()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - UI
|
|
|
|
|
|
|
|
private extension DocumentView {
|
2022-12-18 01:08:38 +01:00
|
|
|
var isToolbarDisabled: Bool { loadedData == nil }
|
|
|
|
|
2022-12-16 01:47:44 +01:00
|
|
|
@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
|
|
|
|
|
2022-12-20 02:05:22 +01:00
|
|
|
var supportedContentTypes: [String] {
|
|
|
|
[.ContentType.jpeg, .ContentType.png]
|
|
|
|
}
|
|
|
|
|
2022-12-16 01:47:44 +01:00
|
|
|
var imageFromData: UIImage {
|
|
|
|
guard
|
|
|
|
let loadedData,
|
|
|
|
let image = UIImage(data: loadedData)
|
|
|
|
else {
|
|
|
|
return .init()
|
|
|
|
}
|
|
|
|
|
|
|
|
return image
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Functions
|
|
|
|
|
|
|
|
func loadDataIfPossible() async {
|
2022-12-20 02:05:22 +01:00
|
|
|
guard supportedContentTypes.contains(document.contentType) else {
|
2022-12-16 01:47:44 +01:00
|
|
|
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 {
|
2022-12-20 02:05:22 +01:00
|
|
|
enum ContentType {
|
|
|
|
static let jpeg = "image/jpeg"
|
|
|
|
static let png = "image/png"
|
2022-12-16 01:47:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|