// // ViewsComponentsToastOverlay.swift // Mobile Music Assistant // // Created by Sven Hanold on 09.04.26. // import SwiftUI // MARK: - Toast Manager @Observable class MAToastManager { private(set) var message: String = "" private(set) var icon: String = "heart.fill" private(set) var iconColor: Color = .red private(set) var isVisible: Bool = false private var hideTask: Task? func show(_ message: String, icon: String = "heart.fill", iconColor: Color = .red) { self.message = message self.icon = icon self.iconColor = iconColor withAnimation(.spring(duration: 0.3)) { isVisible = true } hideTask?.cancel() hideTask = Task { @MainActor in try? await Task.sleep(for: .seconds(2)) guard !Task.isCancelled else { return } withAnimation(.easeOut(duration: 0.4)) { isVisible = false } } } } // MARK: - Toast View Modifier struct ToastOverlayModifier: ViewModifier { @Environment(MAToastManager.self) private var toastManager func body(content: Content) -> some View { content.overlay(alignment: .top) { if toastManager.isVisible { HStack(spacing: 8) { Image(systemName: toastManager.icon) .foregroundStyle(toastManager.iconColor) Text(toastManager.message) .font(.subheadline.weight(.medium)) .lineLimit(1) } .padding(.horizontal, 18) .padding(.vertical, 11) .background(.ultraThinMaterial, in: Capsule()) .shadow(color: .black.opacity(0.15), radius: 8, y: 4) .padding(.top, 12) .transition(.move(edge: .top).combined(with: .opacity)) } } } } extension View { func withToast() -> some View { modifier(ToastOverlayModifier()) } }