@@ -19,17 +19,15 @@ struct OnboardingView: View {
19
19
var isSmallDevice : Bool {
20
20
UIScreen . main. isPhoneSE
21
21
}
22
+ @State private var animateContent = false
22
23
23
24
var body : some View {
24
-
25
25
ZStack {
26
26
Color ( uiColor: . systemBackground)
27
27
. ignoresSafeArea ( )
28
28
29
29
VStack {
30
-
31
30
HStack ( alignment: . center, spacing: 40 ) {
32
-
33
31
Spacer ( )
34
32
35
33
if viewModel. words. isEmpty {
@@ -41,6 +39,12 @@ struct OnboardingView: View {
41
39
}
42
40
. tint ( . secondary)
43
41
. font ( . title)
42
+ . opacity ( animateContent ? 1 : 0 )
43
+ . offset ( x: animateContent ? 0 : 100 )
44
+ . animation (
45
+ . spring( response: 0.6 , dampingFraction: 0.7 ) . delay ( 1.2 ) ,
46
+ value: animateContent
47
+ )
44
48
45
49
Button {
46
50
if let clipboardContent = UIPasteboard . general. string {
@@ -52,6 +56,12 @@ struct OnboardingView: View {
52
56
}
53
57
. tint ( . secondary)
54
58
. font ( . title)
59
+ . opacity ( animateContent ? 1 : 0 )
60
+ . offset ( x: animateContent ? 0 : 100 )
61
+ . animation (
62
+ . spring( response: 0.6 , dampingFraction: 0.7 ) . delay ( 1.3 ) ,
63
+ value: animateContent
64
+ )
55
65
} else {
56
66
Button {
57
67
viewModel. words = " "
@@ -67,28 +77,26 @@ struct OnboardingView: View {
67
77
68
78
Spacer ( )
69
79
70
- VStack (
71
- spacing: isSmallDevice ? 5 : 25
72
- ) {
80
+ VStack ( spacing: isSmallDevice ? 5 : 25 ) {
73
81
Image ( systemName: " bitcoinsign.circle " )
74
82
. resizable ( )
75
- . foregroundStyle (
76
- . secondary
77
- )
83
+ . foregroundStyle ( . secondary)
78
84
. frame (
79
85
width: isSmallDevice ? 40 : 100 ,
80
86
height: isSmallDevice ? 40 : 100 ,
81
87
alignment: . center
82
88
)
89
+ . scaleEffect ( animateContent ? 1 : 0 )
90
+ . opacity ( animateContent ? 1 : 0 )
91
+ . animation (
92
+ . spring( response: 0.6 , dampingFraction: 0.5 , blendDuration: 0.6 ) ,
93
+ value: animateContent
94
+ )
95
+
83
96
Text ( " powered by Bitcoin Dev Kit " )
84
97
. foregroundStyle (
85
98
LinearGradient (
86
- gradient: Gradient (
87
- colors: [
88
- . secondary,
89
- . primary,
90
- ]
91
- ) ,
99
+ gradient: Gradient ( colors: [ . secondary, . primary] ) ,
92
100
startPoint: . topLeading,
93
101
endPoint: . bottomTrailing
94
102
)
@@ -97,39 +105,41 @@ struct OnboardingView: View {
97
105
. fontWeight ( . medium)
98
106
. multilineTextAlignment ( . center)
99
107
. padding ( )
108
+ . opacity ( animateContent ? 1 : 0 )
109
+ . animation ( . easeOut( duration: 0.5 ) . delay ( 0.6 ) , value: animateContent)
100
110
}
101
111
. padding ( )
102
112
103
- Picker (
104
- " Network " ,
105
- selection: $viewModel. selectedNetwork
106
- ) {
107
- Text ( " Signet " ) . tag ( Network . signet)
108
- Text ( " Testnet " ) . tag ( Network . testnet)
109
- }
110
- . pickerStyle ( . automatic)
111
- . tint ( . primary)
112
- . accessibilityLabel ( " Select Bitcoin Network " )
113
-
114
- Picker (
115
- " Esplora Server " ,
116
- selection: $viewModel. selectedURL
117
- ) {
118
- ForEach ( viewModel. availableURLs, id: \. self) { url in
119
- Text (
120
- url. replacingOccurrences (
121
- of: " https:// " ,
122
- with: " "
123
- ) . replacingOccurrences (
124
- of: " http:// " ,
125
- with: " "
113
+ Group {
114
+ Picker ( " Network " , selection: $viewModel. selectedNetwork) {
115
+ Text ( " Signet " ) . tag ( Network . signet)
116
+ Text ( " Testnet " ) . tag ( Network . testnet)
117
+ }
118
+ . pickerStyle ( . automatic)
119
+ . tint ( . primary)
120
+ . accessibilityLabel ( " Select Bitcoin Network " )
121
+ . opacity ( animateContent ? 1 : 0 )
122
+ . animation ( . easeOut( duration: 0.5 ) . delay ( 1.5 ) , value: animateContent)
123
+
124
+ Picker ( " Esplora Server " , selection: $viewModel. selectedURL) {
125
+ ForEach ( viewModel. availableURLs, id: \. self) { url in
126
+ Text (
127
+ url. replacingOccurrences (
128
+ of: " https:// " ,
129
+ with: " "
130
+ ) . replacingOccurrences (
131
+ of: " http:// " ,
132
+ with: " "
133
+ )
126
134
)
127
- )
128
- . tag ( url )
135
+ . tag ( url )
136
+ }
129
137
}
138
+ . pickerStyle ( . automatic)
139
+ . tint ( . primary)
140
+ . opacity ( animateContent ? 1 : 0 )
141
+ . animation ( . easeOut( duration: 0.5 ) . delay ( 1.5 ) , value: animateContent)
130
142
}
131
- . pickerStyle ( . automatic)
132
- . tint ( . primary)
133
143
134
144
if !viewModel. words. isEmpty {
135
145
if viewModel. isDescriptor || viewModel. isXPub {
@@ -165,9 +175,13 @@ struct OnboardingView: View {
165
175
)
166
176
)
167
177
. padding ( )
168
-
178
+ . opacity ( animateContent ? 1 : 0 )
179
+ . offset ( y: animateContent ? 0 : 50 )
180
+ . animation (
181
+ . spring( response: 0.6 , dampingFraction: 0.7 ) . delay ( 1.2 ) ,
182
+ value: animateContent
183
+ )
169
184
}
170
-
171
185
}
172
186
. alert ( isPresented: $showingOnboardingViewErrorAlert) {
173
187
Alert (
@@ -196,7 +210,11 @@ struct OnboardingView: View {
196
210
pasteAction: { }
197
211
)
198
212
}
199
-
213
+ . onAppear {
214
+ withAnimation {
215
+ animateContent = true
216
+ }
217
+ }
200
218
}
201
219
}
202
220
0 commit comments