feat(android): implement snackbar overlay behavior
This commit is contained in:
@@ -3,13 +3,51 @@ import SwiftUI
|
||||
struct SnackbarOverlay: View {
|
||||
#if os(Android)
|
||||
let center: SnackbarCenter
|
||||
@State var current: SnackbarMessage?
|
||||
@State var observer: Any?
|
||||
#else
|
||||
@ObservedObject var center: SnackbarCenter
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
#if os(Android)
|
||||
EmptyView()
|
||||
VStack {
|
||||
if let message = current {
|
||||
HStack(spacing: 10) {
|
||||
if let icon = message.iconSystemName, !icon.isEmpty {
|
||||
Image(systemName: icon)
|
||||
.font(.system(size: 16, weight: .semibold))
|
||||
}
|
||||
Text(message.title)
|
||||
.font(AppTypography.heading3)
|
||||
.multilineTextAlignment(.leading)
|
||||
.lineLimit(3)
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.foregroundStyle(Color.white)
|
||||
.padding(.top, 14)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, 16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(message.style.backgroundColor)
|
||||
.appContentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
center.handleTap()
|
||||
}
|
||||
.transition(.move(edge: .top).combined(with: .opacity))
|
||||
.zIndex(999)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.animation(.spring(response: 0.3, dampingFraction: 0.9), value: current?.id)
|
||||
.allowsHitTesting(current != nil)
|
||||
.onAppear {
|
||||
current = center.current
|
||||
attachObserverIfNeeded()
|
||||
}
|
||||
.onDisappear {
|
||||
detachObserver()
|
||||
}
|
||||
#else
|
||||
VStack {
|
||||
if let message = center.current {
|
||||
@@ -43,4 +81,25 @@ struct SnackbarOverlay: View {
|
||||
.allowsHitTesting(center.current != nil)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(Android)
|
||||
private func attachObserverIfNeeded() {
|
||||
guard observer == nil else { return }
|
||||
observer = NotificationCenter.default.addObserver(
|
||||
forName: .snackbarDidChange,
|
||||
object: nil,
|
||||
queue: nil
|
||||
) { _ in
|
||||
Task { @MainActor in
|
||||
current = center.current
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func detachObserver() {
|
||||
guard let observer else { return }
|
||||
NotificationCenter.default.removeObserver(observer)
|
||||
self.observer = nil
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user