refactor(toast): 공통 토스트 모디파이어를 적용한다

This commit is contained in:
Yu Sung
2026-03-13 16:32:57 +09:00
parent 19f5cc8ad6
commit fb85f3e90c
95 changed files with 261 additions and 1729 deletions

View File

@@ -36,3 +36,99 @@ struct BaseView_Previews: PreviewProvider {
BaseView(isLoading: .constant(false)) {}
}
}
private struct SodaToastModifier: ViewModifier {
@Binding var isPresented: Bool
let message: String
let autohideIn: Double
private let toastBackgroundColor = Color(
red: 59.0 / 255.0,
green: 185.0 / 255.0,
blue: 241.0 / 255.0,
opacity: 0.92
)
@State private var dismissWorkItem: DispatchWorkItem?
func body(content: Content) -> some View {
content
.overlay(alignment: .top) {
GeometryReader { geo in
if isPresented, !message.isEmpty {
Text(message)
.appFont(size: 12, weight: .medium)
.foregroundColor(.white)
.multilineTextAlignment(.center)
.lineLimit(2)
.padding(.horizontal, 18)
.padding(.vertical, 12)
.background(
Capsule()
.fill(toastBackgroundColor)
)
.overlay(
Capsule()
.stroke(Color.white.opacity(0.15), lineWidth: 1)
)
.padding(.top, geo.safeAreaInsets.top + 8)
.padding(.horizontal, 24)
.frame(maxWidth: .infinity, alignment: .top)
.transition(.move(edge: .top).combined(with: .opacity))
}
}
.allowsHitTesting(false)
}
.animation(.easeInOut(duration: 0.2), value: isPresented)
.onAppear {
if isPresented {
scheduleDismiss()
}
}
.onChange(of: isPresented) { newValue in
if newValue {
scheduleDismiss()
} else {
cancelDismiss()
}
}
.onDisappear {
cancelDismiss()
}
}
private func scheduleDismiss() {
cancelDismiss()
guard autohideIn > 0 else {
return
}
let workItem = DispatchWorkItem {
withAnimation {
isPresented = false
}
}
dismissWorkItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + autohideIn, execute: workItem)
}
private func cancelDismiss() {
dismissWorkItem?.cancel()
dismissWorkItem = nil
}
}
extension View {
func sodaToast(isPresented: Binding<Bool>, message: String, autohideIn: Double = 2) -> some View {
modifier(
SodaToastModifier(
isPresented: isPresented,
message: message,
autohideIn: autohideIn
)
)
}
}