Skip to content

Commit 615274d

Browse files
committed
머지
2 parents 35ec5ef + 4aee930 commit 615274d

File tree

18 files changed

+1492
-632
lines changed

18 files changed

+1492
-632
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "Home.svg",
5+
"idiom" : "universal",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"author" : "xcode",
19+
"version" : 1
20+
}
21+
}
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import SwiftUI
2+
3+
enum FancyToastStyle {
4+
case error
5+
case warning
6+
case success
7+
case info
8+
}
9+
10+
extension FancyToastStyle {
11+
var themeColor: Color {
12+
switch self {
13+
case .error: return Color.red
14+
case .warning: return Color.orange
15+
case .info: return GPleAsset.Color.main.swiftUIColor
16+
case .success: return Color.green
17+
}
18+
}
19+
20+
var iconFileName: String {
21+
switch self {
22+
case .info: return "info.circle.fill"
23+
case .warning: return "exclamationmark.triangle.fill"
24+
case .success: return "checkmark.circle.fill"
25+
case .error: return "xmark.circle.fill"
26+
}
27+
}
28+
}
29+
30+
struct FancyToast: Equatable {
31+
var type: FancyToastStyle
32+
var title: String
33+
var message: String
34+
var duration: Double = 3
35+
}
36+
37+
struct FancyToastView: View {
38+
var type: FancyToastStyle
39+
var title: String
40+
var message: String
41+
var onCancelTapped: (() -> Void)
42+
var body: some View {
43+
VStack(alignment: .leading) {
44+
HStack(alignment: .top) {
45+
Image(systemName: type.iconFileName)
46+
.foregroundColor(type.themeColor)
47+
48+
VStack(alignment: .leading) {
49+
Text(title)
50+
.font(.system(size: 14, weight: .semibold))
51+
52+
Text(message)
53+
.font(.system(size: 12))
54+
.foregroundColor(Color.black.opacity(0.6))
55+
}
56+
57+
Spacer(minLength: 10)
58+
59+
Button {
60+
onCancelTapped()
61+
} label: {
62+
Image(systemName: "xmark")
63+
.foregroundColor(Color.black)
64+
}
65+
}
66+
.padding()
67+
}
68+
.background(Color.white)
69+
.overlay(
70+
Rectangle()
71+
.fill(type.themeColor)
72+
.frame(width: 6)
73+
.clipped()
74+
, alignment: .leading
75+
)
76+
.frame(minWidth: 0, maxWidth: .infinity)
77+
.cornerRadius(8)
78+
.shadow(color: Color.black.opacity(0.25), radius: 4, x: 0, y: 1)
79+
.padding(.horizontal, 16)
80+
}
81+
}
82+
83+
struct FancyToastModifier: ViewModifier {
84+
@Binding var toast: FancyToast?
85+
@State private var workItem: DispatchWorkItem?
86+
87+
func body(content: Content) -> some View {
88+
content
89+
.frame(maxWidth: .infinity, maxHeight: .infinity)
90+
.overlay(
91+
ZStack {
92+
mainToastView()
93+
.offset(y: -30)
94+
}.animation(.spring(), value: toast)
95+
)
96+
.onChange(of: toast) { value in
97+
showToast()
98+
}
99+
}
100+
101+
@ViewBuilder func mainToastView() -> some View {
102+
if let toast = toast {
103+
VStack {
104+
FancyToastView(
105+
type: toast.type,
106+
title: toast.title,
107+
message: toast.message) {
108+
dismissToast()
109+
}
110+
Spacer()
111+
}
112+
.transition(.move(edge: .top))
113+
.padding(.top, 35)
114+
}
115+
}
116+
117+
private func showToast() {
118+
guard let toast = toast else { return }
119+
120+
UIImpactFeedbackGenerator(style: .light).impactOccurred()
121+
122+
if toast.duration > 0 {
123+
workItem?.cancel()
124+
125+
let task = DispatchWorkItem {
126+
dismissToast()
127+
}
128+
129+
workItem = task
130+
DispatchQueue.main.asyncAfter(deadline: .now() + toast.duration, execute: task)
131+
}
132+
}
133+
134+
private func dismissToast() {
135+
withAnimation {
136+
toast = nil
137+
}
138+
139+
workItem?.cancel()
140+
workItem = nil
141+
}
142+
}
143+
144+
extension View {
145+
func toastView(toast: Binding<FancyToast?>) -> some View {
146+
self.modifier(FancyToastModifier(toast: toast))
147+
}
148+
}

0 commit comments

Comments
 (0)