mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-03 04:48:50 +00:00
Error state UI
This commit is contained in:
parent
f9f6ffc71e
commit
039f786c16
7 changed files with 78 additions and 8 deletions
|
@ -38,10 +38,18 @@ public struct ConversationsListView: View {
|
||||||
}
|
}
|
||||||
Divider()
|
Divider()
|
||||||
}
|
}
|
||||||
} else if conversations.isEmpty && !viewModel.isLoadingFirstPage {
|
} else if conversations.isEmpty && !viewModel.isLoadingFirstPage && !viewModel.isError {
|
||||||
EmptyView(iconName: "tray",
|
EmptyView(iconName: "tray",
|
||||||
title: "Inbox Zero",
|
title: "Inbox Zero",
|
||||||
message: "Looking for some social media love? You'll find all your direct messages and private mentions right here. Happy messaging! 📱❤️")
|
message: "Looking for some social media love? You'll find all your direct messages and private mentions right here. Happy messaging! 📱❤️")
|
||||||
|
} else if viewModel.isError {
|
||||||
|
ErrorView(title: "An error occurred",
|
||||||
|
message: "Error while loading your messages",
|
||||||
|
buttonTitle: "Retry") {
|
||||||
|
Task {
|
||||||
|
await viewModel.fetchConversations()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.top, .layoutPadding)
|
.padding(.top, .layoutPadding)
|
||||||
|
|
|
@ -8,6 +8,7 @@ class ConversationsListViewModel: ObservableObject {
|
||||||
|
|
||||||
@Published var isLoadingFirstPage: Bool = true
|
@Published var isLoadingFirstPage: Bool = true
|
||||||
@Published var conversations: [Conversation] = []
|
@Published var conversations: [Conversation] = []
|
||||||
|
@Published var isError: Bool = false
|
||||||
|
|
||||||
public init() { }
|
public init() { }
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ class ConversationsListViewModel: ObservableObject {
|
||||||
conversations = try await client.get(endpoint: Conversations.conversations)
|
conversations = try await client.get(endpoint: Conversations.conversations)
|
||||||
isLoadingFirstPage = false
|
isLoadingFirstPage = false
|
||||||
} catch {
|
} catch {
|
||||||
|
isError = true
|
||||||
isLoadingFirstPage = false
|
isLoadingFirstPage = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
public struct ErrorView: View {
|
||||||
|
public let title: String
|
||||||
|
public let message: String
|
||||||
|
public let buttonTitle: String
|
||||||
|
public let onButtonPress: (() -> Void)
|
||||||
|
|
||||||
|
public init(title: String, message: String, buttonTitle: String, onButtonPress: @escaping (() -> Void)) {
|
||||||
|
self.title = title
|
||||||
|
self.message = message
|
||||||
|
self.buttonTitle = buttonTitle
|
||||||
|
self.onButtonPress = onButtonPress
|
||||||
|
}
|
||||||
|
|
||||||
|
public var body: some View {
|
||||||
|
VStack {
|
||||||
|
Image(systemName: "exclamationmark.triangle.fill")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(maxHeight: 50)
|
||||||
|
Text(title)
|
||||||
|
.font(.title)
|
||||||
|
.padding(.top, 16)
|
||||||
|
Text(message)
|
||||||
|
.font(.subheadline)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
Button {
|
||||||
|
onButtonPress()
|
||||||
|
} label: {
|
||||||
|
Text(buttonTitle)
|
||||||
|
}
|
||||||
|
.buttonStyle(.bordered)
|
||||||
|
.padding(.top, 16)
|
||||||
|
}
|
||||||
|
.padding(.top, 100)
|
||||||
|
.padding(.layoutPadding)
|
||||||
|
}
|
||||||
|
}
|
|
@ -102,8 +102,14 @@ public struct NotificationsListView: View {
|
||||||
loadingRow
|
loadingRow
|
||||||
}
|
}
|
||||||
|
|
||||||
case let .error(error):
|
case .error:
|
||||||
Text(error.localizedDescription)
|
ErrorView(title: "An error occured",
|
||||||
|
message: "An error occured while loading your notifications, please retry.",
|
||||||
|
buttonTitle: "Retry") {
|
||||||
|
Task {
|
||||||
|
await viewModel.fetchNotifications()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,14 @@ public struct StatusDetailView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case let .error(error):
|
case .error:
|
||||||
Text(error.localizedDescription)
|
ErrorView(title: "An error occured",
|
||||||
.padding(.horizontal, .layoutPadding)
|
message: "An error occured while this post context, please try again.",
|
||||||
|
buttonTitle: "Retry") {
|
||||||
|
Task {
|
||||||
|
await viewModel.fetch()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.top, .layoutPadding)
|
.padding(.top, .layoutPadding)
|
||||||
|
|
|
@ -24,8 +24,15 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
|
||||||
Divider()
|
Divider()
|
||||||
.padding(.vertical, .dividerPadding)
|
.padding(.vertical, .dividerPadding)
|
||||||
}
|
}
|
||||||
case let .error(error):
|
case .error:
|
||||||
Text(error.localizedDescription)
|
ErrorView(title: "An error occured",
|
||||||
|
message: "An error occured while loading posts, please try again.",
|
||||||
|
buttonTitle: "Retry") {
|
||||||
|
Task {
|
||||||
|
await fetcher.fetchStatuses()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case let .display(statuses, nextPageState):
|
case let .display(statuses, nextPageState):
|
||||||
ForEach(statuses, id: \.viewId) { status in
|
ForEach(statuses, id: \.viewId) { status in
|
||||||
StatusRowView(viewModel: .init(status: status, isCompact: false, isRemote: isRemote))
|
StatusRowView(viewModel: .init(status: status, isCompact: false, isRemote: isRemote))
|
||||||
|
|
|
@ -38,6 +38,8 @@ struct StatusRowContextMenu: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
if let url = viewModel.status.reblog?.url ?? viewModel.status.url {
|
if let url = viewModel.status.reblog?.url ?? viewModel.status.url {
|
||||||
ShareLink(item: url) {
|
ShareLink(item: url) {
|
||||||
Label("Share this post", systemImage: "square.and.arrow.up")
|
Label("Share this post", systemImage: "square.and.arrow.up")
|
||||||
|
|
Loading…
Reference in a new issue