Implemented the support for the view status in the BrowseView view for the Browse module.

This commit is contained in:
Javier Cicchelli 2022-12-15 02:13:14 +01:00
parent 3e70186959
commit c735bd0381
2 changed files with 103 additions and 37 deletions

View File

@ -38,6 +38,8 @@ struct ContentView: View {
// TODO: upload a new file // TODO: upload a new file
} showProfile: { } showProfile: {
showSheet = .profile showSheet = .profile
} login: {
showSheet = .login
} }
.sheet(item: $showSheet) { sheet in .sheet(item: $showSheet) { sheet in
switch sheet { switch sheet {
@ -71,6 +73,7 @@ private extension ContentView {
let createFolder: ActionClosure let createFolder: ActionClosure
let uploadFile: ActionClosure let uploadFile: ActionClosure
let showProfile: ActionClosure let showProfile: ActionClosure
let login: ActionClosure
// MARK: Body // MARK: Body
@ -84,7 +87,8 @@ private extension ContentView {
), ),
createFolder: createFolder, createFolder: createFolder,
uploadFile: uploadFile, uploadFile: uploadFile,
showProfile: showProfile showProfile: showProfile,
login: login
) )
} }
} else { } else {

View File

@ -18,6 +18,7 @@ public struct BrowseView: View {
// MARK: States // MARK: States
@State private var status: ViewStatus = .loading
@State private var items: [any FileSystemItemIdentifiable] = [] @State private var items: [any FileSystemItemIdentifiable] = []
@State private var stack: Stack? @State private var stack: Stack?
@ -27,6 +28,7 @@ public struct BrowseView: View {
private let createFolder: ActionClosure private let createFolder: ActionClosure
private let uploadFile: ActionClosure private let uploadFile: ActionClosure
private let showProfile: ActionClosure private let showProfile: ActionClosure
private let login: ActionClosure
private let getItems: GetItemsUseCase = .init() private let getItems: GetItemsUseCase = .init()
@ -36,51 +38,83 @@ public struct BrowseView: View {
folder: Folder, folder: Folder,
createFolder: @escaping ActionClosure, createFolder: @escaping ActionClosure,
uploadFile: @escaping ActionClosure, uploadFile: @escaping ActionClosure,
showProfile: @escaping ActionClosure showProfile: @escaping ActionClosure,
login: @escaping ActionClosure
) { ) {
self.folder = folder self.folder = folder
self.createFolder = createFolder self.createFolder = createFolder
self.uploadFile = uploadFile self.uploadFile = uploadFile
self.showProfile = showProfile self.showProfile = showProfile
self.login = login
} }
// MARK: Body // MARK: Body
public var body: some View { public var body: some View {
List(items, id: \.id) { item in content
switch item { .navigationTitle(folder.name)
case is Folder: .toolbar {
makeFolderItem(for: item) BrowseToolbar(
case is Document: createFolder: createFolder,
DocumentItem(item: item) { uploadFile: uploadFile,
// TODO: show the item id in a viewer... showProfile: showProfile
} download: { )
// TODO: download the item id from the backend. }
} delete: { .task(id: folder) {
// TODO: delete the item id from the backend. await loadItems()
}
default:
EmptyView()
} }
}
.listStyle(.inset)
.navigationTitle(folder.name)
.toolbar {
BrowseToolbar(
createFolder: createFolder,
uploadFile: uploadFile,
showProfile: showProfile
)
}
.task(id: folder) {
await getItemsOrStop()
}
} }
} }
// MARK: - UI // MARK: - UI
private extension BrowseView { private extension BrowseView {
// MARK: Properties
@ViewBuilder var content: some View {
switch status {
case .noCredentials:
MessageView(
type: .noCredentials,
action: login
)
case .loading:
LoadingView()
case .loaded:
List(items, id: \.id) { item in
switch item {
case is Folder:
makeFolderItem(for: item)
case is Document:
DocumentItem(item: item) {
// TODO: show the item id in a viewer...
} download: {
// TODO: download the item id from the backend.
} delete: {
// TODO: delete the item id from the backend.
}
default:
EmptyView()
}
}
.listStyle(.inset)
case .empty:
MessageView(
type: .empty,
action: uploadFile
)
case .error:
MessageView(type: .error) {
Task {
await loadItems()
}
}
}
}
// MARK: Functions
@ViewBuilder func makeFolderItem( @ViewBuilder func makeFolderItem(
for item: any FileSystemItemIdentifiable for item: any FileSystemItemIdentifiable
) -> some View { ) -> some View {
@ -99,32 +133,58 @@ private extension BrowseView {
folder: folder, folder: folder,
createFolder: createFolder, createFolder: createFolder,
uploadFile: uploadFile, uploadFile: uploadFile,
showProfile: showProfile showProfile: showProfile,
login: login
), ),
tagged: .browse(folder), tagged: .browse(folder),
in: $stack in: $stack
) )
} }
} }
// MARK: - Helpers // MARK: - Helpers
private extension BrowseView { private extension BrowseView {
func getItemsOrStop() async { func loadItems() async {
guard let account else { return } guard let account else {
status = .noCredentials
return
}
do { do {
items = try await getItems( status = .loading
let loadedItems = try await getItems(
id: folder.id, id: folder.id,
username: account.username, username: account.username,
password: account.password password: account.password
) )
if loadedItems.isEmpty {
status = .empty
} else {
items = loadedItems
status = .loaded
}
} catch { } catch {
// TODO: handle the error appropriately. status = .error
} }
} }
} }
// MARK: - Enumerations
private extension BrowseView {
enum ViewStatus {
case noCredentials
case loading
case loaded
case empty
case error
}
}
// MARK: - Previews // MARK: - Previews
struct BrowseView_Previews: PreviewProvider { struct BrowseView_Previews: PreviewProvider {
@ -134,11 +194,13 @@ struct BrowseView_Previews: PreviewProvider {
id: UUID().uuidString, id: UUID().uuidString,
name: "Some folder name" name: "Some folder name"
)) { )) {
// ... // create folder closure.
} uploadFile: { } uploadFile: {
// ... // upload file closure.
} showProfile: { } showProfile: {
// ... // show profile closure.
} login: {
// login closure.
} }
} }
} }