Consolidate snackbar state into a SnackbarOperation struct

This commit is contained in:
Jackson Harper
2023-07-14 13:49:18 +08:00
parent d80358bdb9
commit e9405d9738
3 changed files with 30 additions and 19 deletions

View File

@ -62,7 +62,7 @@ struct InnerRootView: View {
}
}
#endif
.snackBar(isShowing: $viewModel.showSnackbar, message: viewModel.snackbarMessage, undoAction: viewModel.snackBarUndoAction)
.snackBar(isShowing: $viewModel.showSnackbar, operation: viewModel.snackbarOperation)
// Schedule the dismissal every time we present the snackbar.
.onChange(of: viewModel.showSnackbar) { newValue in
if newValue {
@ -93,15 +93,15 @@ struct InnerRootView: View {
#if os(iOS)
.onReceive(NSNotification.operationSuccessPublisher) { notification in
if let message = notification.userInfo?["message"] as? String {
viewModel.snackbarMessage = message
viewModel.snackBarUndoAction = notification.userInfo?["undoAction"] as? (() -> Void)
viewModel.snackbarOperation = SnackbarOperation(message: message,
undoAction: notification.userInfo?["undoAction"] as? SnackbarUndoAction)
viewModel.showSnackbar = true
}
}
.onReceive(NSNotification.operationFailedPublisher) { notification in
if let message = notification.userInfo?["message"] as? String {
viewModel.showSnackbar = true
viewModel.snackbarMessage = message
viewModel.snackbarOperation = SnackbarOperation(message: message, undoAction: nil)
}
}
#endif

View File

@ -17,10 +17,9 @@ public final class RootViewModel: ObservableObject {
@Published public var showNewFeaturePrimer = false
@AppStorage(UserDefaultKey.shouldShowNewFeaturePrimer.rawValue) var shouldShowNewFeaturePrimer = false
@Published var snackbarMessage: String?
@Published var showMiniPlayer = false
@Published var showSnackbar = false
@Published var snackBarUndoAction: (() -> Void)?
@Published var showMiniPlayer = true
@Published var snackbarOperation: SnackbarOperation?
public init() {
registerFonts()

View File

@ -1,24 +1,32 @@
import SwiftUI
public typealias SnackbarUndoAction = (() -> Void)
public struct SnackbarOperation {
let message: String
let undoAction: SnackbarUndoAction?
public init(message: String, undoAction: SnackbarUndoAction?) {
self.message = message
self.undoAction = undoAction
}
}
public struct Snackbar: View {
@Binding var isShowing: Bool
private let presentingView: AnyView
private let text: Text
private let undoAction: (() -> Void)?
private let operation: SnackbarOperation
@Environment(\.colorScheme) private var colorScheme: ColorScheme
init<PresentingView>(
isShowing: Binding<Bool>,
presentingView: PresentingView,
text: Text,
undoAction: (() -> Void)?
operation: SnackbarOperation
) where PresentingView: View {
self._isShowing = isShowing
self.presentingView = AnyView(presentingView)
self.text = text
self.undoAction = undoAction
self.operation = operation
}
public var body: some View {
@ -27,13 +35,13 @@ public struct Snackbar: View {
presentingView
VStack {
Spacer()
if self.isShowing {
if isShowing {
HStack {
self.text
Text(operation.message)
.font(.appCallout)
.foregroundColor(self.colorScheme == .light ? .white : .appTextDefault)
Spacer()
if let undoAction = undoAction {
if let undoAction = operation.undoAction {
Button("Undo", action: undoAction)
.font(.system(size: 16, weight: .bold))
}
@ -53,7 +61,11 @@ public struct Snackbar: View {
}
public extension View {
func snackBar(isShowing: Binding<Bool>, message: String?, undoAction: (() -> Void)?) -> some View {
Snackbar(isShowing: isShowing, presentingView: self, text: Text(message ?? ""), undoAction: undoAction)
func snackBar(isShowing: Binding<Bool>, operation: SnackbarOperation?) -> some View {
if let operation = operation {
return AnyView(Snackbar(isShowing: isShowing, presentingView: self, operation: operation))
} else {
return AnyView(self)
}
}
}