@@ -24,22 +24,20 @@ import androidx.compose.ui.Alignment
2424import androidx.compose.ui.Modifier
2525import androidx.compose.ui.res.painterResource
2626import androidx.compose.ui.res.stringResource
27+ import androidx.compose.ui.tooling.preview.Preview
2728import androidx.compose.ui.unit.dp
2829import kotlinx.coroutines.delay
2930import kotlinx.coroutines.launch
3031import to.bitkit.R
3132import to.bitkit.ext.DatePattern
3233import to.bitkit.ext.ellipsisMiddle
3334import to.bitkit.ext.formatted
34- import to.bitkit.ext.truncate
3535import to.bitkit.ui.components.BalanceHeaderView
3636import to.bitkit.ui.components.BodySSB
3737import to.bitkit.ui.components.Caption13Up
38- import to.bitkit.ui.components.Display
38+ import to.bitkit.ui.components.PrimaryButton
3939import to.bitkit.ui.components.SwipeToConfirm
4040import to.bitkit.ui.scaffold.SheetTopBar
41- import to.bitkit.ui.shared.moneyString
42- import to.bitkit.ui.shared.util.DarkModePreview
4341import to.bitkit.ui.theme.AppThemeSurface
4442import to.bitkit.ui.theme.Colors
4543import to.bitkit.viewmodels.SendEvent
@@ -70,136 +68,33 @@ fun SendAndReviewScreen(
7068 .padding(horizontal = 16 .dp)
7169 .fillMaxWidth()
7270 ) {
73-
7471 BalanceHeaderView (sats = uiState.amount.toLong(), modifier = Modifier .fillMaxWidth())
7572
7673 Spacer (modifier = Modifier .height(16 .dp))
7774
78- Caption13Up (
79- text = stringResource(
80- if (uiState.payMethod == SendMethod .ONCHAIN ) R .string.wallet__send_to else R .string.wallet__send_invoice
81- ),
82- color = Colors .White64 ,
83- )
84- val destination = when (uiState.payMethod) {
85- SendMethod .ONCHAIN -> uiState.address.ellipsisMiddle(25 )
86- SendMethod .LIGHTNING -> uiState.bolt11?.truncate(100 ) ? : " "
75+ when (uiState.payMethod) {
76+ SendMethod .ONCHAIN -> OnChainDescription (uiState = uiState, onEvent = onEvent)
77+ SendMethod .LIGHTNING -> LightningDescription (uiState = uiState, onEvent = onEvent)
8778 }
79+
80+ Spacer (modifier = Modifier .height(16 .dp))
81+ Caption13Up (text = stringResource(R .string.wallet__tags), color = Colors .White64 )
8882 Spacer (modifier = Modifier .height(8 .dp))
89- BodySSB (text = destination)
83+ // TODO DISPLAY TAGS
84+ PrimaryButton (
85+ stringResource(R .string.wallet__tags_add),
86+ onClick = {}, // TODO IMPLEMENT
87+ icon = {
88+ Icon (
89+ painter = painterResource(R .drawable.ic_tag),
90+ contentDescription = null ,
91+ tint = Colors .Brand
92+ )
93+ },
94+ fullWidth = false
95+ )
9096 HorizontalDivider (modifier = Modifier .padding(top = 16 .dp))
9197
92- Row (
93- horizontalArrangement = Arrangement .spacedBy(16 .dp),
94- modifier = Modifier .height(IntrinsicSize .Min )
95- ) {
96- if (uiState.payMethod == SendMethod .ONCHAIN ) {
97- Column (
98- modifier = Modifier
99- .fillMaxHeight()
100- .weight(1f )
101- .clickable { onEvent(SendEvent .SpeedAndFee ) }
102- .padding(top = 16 .dp)
103- ) {
104- Caption13Up (text = stringResource(R .string.label_speed), color = Colors .White64 )
105- Spacer (modifier = Modifier .height(8 .dp))
106- BodySSB (text = " Todo Normal (₿ 210)" )
107- Spacer (modifier = Modifier .weight(1f ))
108- HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
109- }
110- Column (
111- modifier = Modifier
112- .fillMaxHeight()
113- .weight(1f )
114- .clickable { onEvent(SendEvent .SpeedAndFee ) }
115- .padding(top = 16 .dp)
116- ) {
117- Caption13Up (text = stringResource(R .string.label_confirms_in), color = Colors .White64 )
118- Spacer (modifier = Modifier .height(8 .dp))
119- BodySSB (text = " Todo ± 20-60 minutes" )
120- Spacer (modifier = Modifier .weight(1f ))
121- HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
122- }
123- } else {
124- Column (
125- modifier = Modifier
126- .fillMaxHeight()
127- .weight(1f )
128- .padding(top = 16 .dp)
129- ) {
130- Caption13Up (text = stringResource(R .string.label_speed), color = Colors .White64 )
131- Spacer (modifier = Modifier .height(8 .dp))
132- Row (
133- verticalAlignment = Alignment .CenterVertically ,
134- horizontalArrangement = Arrangement .spacedBy(4 .dp),
135- ) {
136- Icon (
137- painterResource(R .drawable.ic_speed_normal),
138- contentDescription = null ,
139- tint = Colors .Brand ,
140- modifier = Modifier .size(16 .dp)
141- ) // TODO GET FROM STATE
142- BodySSB (text = " Instant (±$0.01)" ) // TODO GET FROM STATE
143- Icon (
144- painterResource(R .drawable.ic_pencil_simple),
145- contentDescription = null ,
146- tint = Colors .White ,
147- modifier = Modifier .size(16 .dp)
148- )
149- }
150- Spacer (modifier = Modifier .weight(1f ))
151- HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
152- }
153- uiState.decodedInvoice?.expirySeconds?.let { expirySeconds ->
154- Column (
155- modifier = Modifier
156- .fillMaxHeight()
157- .weight(1f )
158- .padding(top = 16 .dp)
159- ) {
160- val invoiceExpiryTimestamp = expirySeconds.let {
161- Instant .now().plusSeconds(it.toLong()).formatted(DatePattern .INVOICE_EXPIRY )
162- }
163- Caption13Up (
164- text = stringResource(R .string.label_invoice_expiration),
165- color = Colors .White64
166- )
167- Spacer (modifier = Modifier .height(8 .dp))
168- Row (
169- verticalAlignment = Alignment .CenterVertically ,
170- horizontalArrangement = Arrangement .spacedBy(4 .dp),
171- ) {
172- Icon (
173- painterResource(R .drawable.ic_clock),
174- contentDescription = null ,
175- tint = Colors .Brand ,
176- modifier = Modifier .size(16 .dp)
177- )
178- BodySSB (text = invoiceExpiryTimestamp)
179- }
180- Spacer (modifier = Modifier .weight(1f ))
181- HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
182- }
183- }
184- }
185- }
186-
187- uiState.decodedInvoice?.description?.let { description ->
188- Column {
189- Caption13Up (text = stringResource(R .string.label_note), color = Colors .White64 )
190- Spacer (modifier = Modifier .height(8 .dp))
191- BodySSB (text = description)
192- HorizontalDivider (modifier = Modifier .padding(top = 16 .dp))
193- }
194- }
195-
196- Column {
197- Spacer (modifier = Modifier .height(16 .dp))
198- Caption13Up (text = stringResource(R .string.label_tags), color = Colors .White64 )
199- Spacer (modifier = Modifier .height(8 .dp))
200- BodySSB (text = " Todo" )
201- }
202-
20398 Spacer (modifier = Modifier .weight(1f ))
20499 SwipeToConfirm (
205100 text = stringResource(R .string.wallet__send_swipe),
@@ -217,8 +112,172 @@ fun SendAndReviewScreen(
217112 }
218113}
219114
115+ @Composable
116+ private fun OnChainDescription (
117+ uiState : SendUiState ,
118+ onEvent : (SendEvent ) -> Unit ,
119+ ) {
120+ Column (modifier = Modifier .fillMaxWidth()) {
121+ Caption13Up (
122+ text = stringResource(R .string.wallet__send_to),
123+ color = Colors .White64 ,
124+ )
125+ val destination = uiState.address.ellipsisMiddle(25 )
126+ Spacer (modifier = Modifier .height(8 .dp))
127+ BodySSB (text = destination)
128+ HorizontalDivider (modifier = Modifier .padding(top = 16 .dp))
129+
130+ Row (
131+ horizontalArrangement = Arrangement .spacedBy(16 .dp),
132+ modifier = Modifier .height(IntrinsicSize .Min )
133+ ) {
134+ Column (
135+ modifier = Modifier
136+ .fillMaxHeight()
137+ .weight(1f )
138+ .clickable { onEvent(SendEvent .SpeedAndFee ) }
139+ .padding(top = 16 .dp)
140+ ) {
141+ Caption13Up (text = stringResource(R .string.wallet__send_fee_and_speed), color = Colors .White64 )
142+ Spacer (modifier = Modifier .height(8 .dp))
143+ Row (
144+ verticalAlignment = Alignment .CenterVertically ,
145+ horizontalArrangement = Arrangement .spacedBy(4 .dp),
146+ ) {
147+ Icon (
148+ painterResource(R .drawable.ic_speed_normal),
149+ contentDescription = null ,
150+ tint = Colors .Brand ,
151+ modifier = Modifier .size(16 .dp)
152+ )
153+ BodySSB (text = " Normal (₿ 210)" ) // TODO GET FROM STATE
154+ Icon (
155+ painterResource(R .drawable.ic_pencil_simple),
156+ contentDescription = null ,
157+ tint = Colors .White ,
158+ modifier = Modifier .size(16 .dp)
159+ )
160+ }
161+ Spacer (modifier = Modifier .weight(1f ))
162+ HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
163+ }
164+ Column (
165+ modifier = Modifier
166+ .fillMaxHeight()
167+ .weight(1f )
168+ .clickable { onEvent(SendEvent .SpeedAndFee ) }
169+ .padding(top = 16 .dp)
170+ ) {
171+ Caption13Up (text = stringResource(R .string.wallet__send_confirming_in), color = Colors .White64 )
172+ Spacer (modifier = Modifier .height(8 .dp))
173+ Row (
174+ verticalAlignment = Alignment .CenterVertically ,
175+ horizontalArrangement = Arrangement .spacedBy(4 .dp),
176+ ) {
177+ Icon (
178+ painterResource(R .drawable.ic_clock),
179+ contentDescription = null ,
180+ tint = Colors .Brand ,
181+ modifier = Modifier .size(16 .dp)
182+ )
183+ BodySSB (text = " ± 20-60 minutes" ) // TODO GET FROM STATE
184+ }
185+ Spacer (modifier = Modifier .weight(1f ))
186+ HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
187+ }
188+
189+ }
190+ }
191+ }
192+
193+ @Composable
194+ private fun LightningDescription (
195+ uiState : SendUiState ,
196+ onEvent : (SendEvent ) -> Unit ,
197+ ) {
198+ Column (modifier = Modifier .fillMaxWidth()) {
199+ Caption13Up (
200+ text = stringResource(R .string.wallet__send_invoice),
201+ color = Colors .White64 ,
202+ )
203+ val destination = uiState.bolt11?.ellipsisMiddle(25 ).orEmpty()
204+ Spacer (modifier = Modifier .height(8 .dp))
205+ BodySSB (text = destination)
206+ HorizontalDivider (modifier = Modifier .padding(top = 16 .dp))
207+
208+ Row (
209+ horizontalArrangement = Arrangement .spacedBy(16 .dp),
210+ modifier = Modifier .height(IntrinsicSize .Min )
211+ ) {
212+ Column (
213+ modifier = Modifier
214+ .fillMaxHeight()
215+ .weight(1f )
216+ .padding(top = 16 .dp)
217+ ) {
218+ Caption13Up (text = stringResource(R .string.wallet__send_fee_and_speed), color = Colors .White64 )
219+ Spacer (modifier = Modifier .height(8 .dp))
220+ Row (
221+ verticalAlignment = Alignment .CenterVertically ,
222+ horizontalArrangement = Arrangement .spacedBy(4 .dp),
223+ ) {
224+ Icon (
225+ painterResource(R .drawable.ic_lightning),
226+ contentDescription = null ,
227+ tint = Colors .Purple ,
228+ modifier = Modifier .size(16 .dp)
229+ )
230+ BodySSB (text = " Instant (±$0.01)" ) // TODO GET FROM STATE
231+ }
232+ Spacer (modifier = Modifier .weight(1f ))
233+ HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
234+ }
235+ uiState.decodedInvoice?.expirySeconds?.let { expirySeconds ->
236+ Column (
237+ modifier = Modifier
238+ .fillMaxHeight()
239+ .weight(1f )
240+ .padding(top = 16 .dp)
241+ ) {
242+ Caption13Up (
243+ text = stringResource(R .string.wallet__send_invoice_expiration),
244+ color = Colors .White64
245+ )
246+ Spacer (modifier = Modifier .height(8 .dp))
247+ Row (
248+ verticalAlignment = Alignment .CenterVertically ,
249+ horizontalArrangement = Arrangement .spacedBy(4 .dp),
250+ ) {
251+ Icon (
252+ painterResource(R .drawable.ic_timer),
253+ contentDescription = null ,
254+ tint = Colors .Purple ,
255+ modifier = Modifier .size(16 .dp)
256+ )
257+ val invoiceExpiryTimestamp = expirySeconds.let {
258+ Instant .now().plusSeconds(it.toLong()).formatted(DatePattern .INVOICE_EXPIRY )
259+ }
260+ BodySSB (text = invoiceExpiryTimestamp)
261+ }
262+ Spacer (modifier = Modifier .weight(1f ))
263+ HorizontalDivider (modifier = Modifier .padding(vertical = 16 .dp))
264+ }
265+ }
266+ }
267+
268+ uiState.decodedInvoice?.description?.let { description ->
269+ Column {
270+ Caption13Up (text = stringResource(R .string.wallet__note), color = Colors .White64 )
271+ Spacer (modifier = Modifier .height(8 .dp))
272+ BodySSB (text = description)
273+ HorizontalDivider (modifier = Modifier .padding(top = 16 .dp))
274+ }
275+ }
276+ }
277+ }
278+
220279@Suppress(" SpellCheckingInspection" )
221- @DarkModePreview
280+ @Preview(name = " Lightning " )
222281@Composable
223282private fun SendAndReviewPreview () {
224283 AppThemeSurface {
@@ -231,7 +290,36 @@ private fun SendAndReviewPreview() {
231290 decodedInvoice = LightningInvoice (
232291 bolt11 = " bcrt123" ,
233292 paymentHash = ByteArray (0 ),
234- amountSatoshis = 0uL ,
293+ amountSatoshis = 100000uL ,
294+ timestampSeconds = 0uL ,
295+ expirySeconds = 3600uL ,
296+ isExpired = false ,
297+ networkType = NetworkType .REGTEST ,
298+ payeeNodeId = null ,
299+ description = " Some invoice description" ,
300+ )
301+ ),
302+ onBack = {},
303+ onEvent = {},
304+ )
305+ }
306+ }
307+
308+ @Suppress(" SpellCheckingInspection" )
309+ @Preview(name = " OnChain" )
310+ @Composable
311+ private fun SendAndReviewPreview2 () {
312+ AppThemeSurface {
313+ SendAndReviewScreen (
314+ uiState = SendUiState (
315+ amount = 1234uL ,
316+ address = " bcrt1qkgfgyxyqhvkdqh04sklnzxphmcds6vft6y7h0r" ,
317+ bolt11 = " lnbcrt1…" ,
318+ payMethod = SendMethod .ONCHAIN ,
319+ decodedInvoice = LightningInvoice (
320+ bolt11 = " bcrt123" ,
321+ paymentHash = ByteArray (0 ),
322+ amountSatoshis = 10000uL ,
235323 timestampSeconds = 0uL ,
236324 expirySeconds = 3600uL ,
237325 isExpired = false ,
0 commit comments