217 lines
5.4 KiB
Swift
217 lines
5.4 KiB
Swift
//
|
|
// BrowseView.swift
|
|
// Browse
|
|
//
|
|
// Created by Javier Cicchelli on 03/12/2022.
|
|
// Copyright © 2022 Röck+Cöde. All rights reserved.
|
|
//
|
|
|
|
import DataModels
|
|
import KeychainStorage
|
|
import SwiftUI
|
|
|
|
public struct BrowseView: View {
|
|
|
|
// MARK: Storages
|
|
|
|
@KeychainStorage(key: .KeychainStorage.account) private var account: Account?
|
|
|
|
// MARK: States
|
|
|
|
@State private var status: ViewStatus = .loading
|
|
@State private var items: [any FileSystemItemable] = []
|
|
@State private var stack: Stack?
|
|
@State private var itemToDelete: (any FileSystemItemable)?
|
|
|
|
// MARK: Properties
|
|
|
|
private let folder: Folder
|
|
private let createFolder: ActionClosure
|
|
private let uploadFile: ActionClosure
|
|
private let showProfile: ActionClosure
|
|
private let login: ActionClosure
|
|
|
|
private let getItems: GetItemsUseCase = .init()
|
|
|
|
// MARK: Initialisers
|
|
|
|
public init(
|
|
folder: Folder,
|
|
createFolder: @escaping ActionClosure,
|
|
uploadFile: @escaping ActionClosure,
|
|
showProfile: @escaping ActionClosure,
|
|
login: @escaping ActionClosure
|
|
) {
|
|
self.folder = folder
|
|
self.createFolder = createFolder
|
|
self.uploadFile = uploadFile
|
|
self.showProfile = showProfile
|
|
self.login = login
|
|
}
|
|
|
|
// MARK: Body
|
|
|
|
public var body: some View {
|
|
content
|
|
.navigationTitle(folder.name)
|
|
.toolbar {
|
|
BrowseToolbar(
|
|
createFolder: createFolder,
|
|
uploadFile: uploadFile,
|
|
showProfile: showProfile
|
|
)
|
|
}
|
|
.delete(item: $itemToDelete)
|
|
.task(id: folder) {
|
|
await loadItems()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - UI
|
|
|
|
private extension BrowseView {
|
|
|
|
// MARK: Properties
|
|
|
|
@ViewBuilder var content: some View {
|
|
switch status {
|
|
case .noCredentials:
|
|
MessageView(
|
|
type: .noCredentials,
|
|
action: login
|
|
)
|
|
case .notSupported:
|
|
EmptyView()
|
|
case .loading:
|
|
LoadingView()
|
|
case .loaded:
|
|
List(items, id: \.id) { item in
|
|
switch item {
|
|
case is Folder:
|
|
makeFolderItem(for: item)
|
|
case is Document:
|
|
makeDocumentItem(for: item)
|
|
default:
|
|
EmptyView()
|
|
}
|
|
}
|
|
.listStyle(.inset)
|
|
case .empty:
|
|
MessageView(
|
|
type: .empty,
|
|
action: uploadFile
|
|
)
|
|
case .error:
|
|
MessageView(type: .error) {
|
|
Task {
|
|
await loadItems()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Functions
|
|
|
|
@ViewBuilder func makeFolderItem(
|
|
for item: any FileSystemItemable
|
|
) -> some View {
|
|
if let folder = item as? Folder {
|
|
FolderItem(item: item) {
|
|
stack = .browse(folder)
|
|
} delete: {
|
|
itemToDelete = item
|
|
}
|
|
.navigate(
|
|
to: BrowseView(
|
|
folder: folder,
|
|
createFolder: createFolder,
|
|
uploadFile: uploadFile,
|
|
showProfile: showProfile,
|
|
login: login
|
|
),
|
|
tagged: .browse(folder),
|
|
in: $stack
|
|
)
|
|
} else {
|
|
EmptyView()
|
|
}
|
|
}
|
|
|
|
@ViewBuilder func makeDocumentItem(
|
|
for item: any FileSystemItemable
|
|
) -> some View {
|
|
if let document = item as? Document {
|
|
DocumentItem(item: item) {
|
|
stack = .open(document)
|
|
} download: {
|
|
// TODO: download the item id from the backend.
|
|
} delete: {
|
|
itemToDelete = item
|
|
}
|
|
.navigate(
|
|
to: DocumentView(
|
|
document: document,
|
|
login: login
|
|
),
|
|
tagged: .open(document),
|
|
in: $stack
|
|
)
|
|
} else {
|
|
EmptyView()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private extension BrowseView {
|
|
func loadItems() async {
|
|
guard let account else {
|
|
status = .noCredentials
|
|
return
|
|
}
|
|
|
|
do {
|
|
status = .loading
|
|
|
|
let loadedItems = try await getItems(
|
|
id: folder.id,
|
|
username: account.username,
|
|
password: account.password
|
|
)
|
|
|
|
if loadedItems.isEmpty {
|
|
status = .empty
|
|
} else {
|
|
items = loadedItems
|
|
status = .loaded
|
|
}
|
|
} catch {
|
|
status = .error
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Previews
|
|
|
|
struct BrowseView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
NavigationView {
|
|
BrowseView(folder: .init(
|
|
id: UUID().uuidString,
|
|
name: "Some folder name"
|
|
)) {
|
|
// create folder closure.
|
|
} uploadFile: {
|
|
// upload file closure.
|
|
} showProfile: {
|
|
// show profile closure.
|
|
} login: {
|
|
// login closure.
|
|
}
|
|
}
|
|
}
|
|
}
|