Skip to content

Commit 8a1189a

Browse files
committed
Merge remote-tracking branch 'origin/develop' into HEAD
* origin/develop: feat: improve bill rendering (images) fix(airdrop): receiveFromPrimary after receiving first airdrop to allow gives after
2 parents 4551355 + f3ad072 commit 8a1189a

10 files changed

Lines changed: 241 additions & 150 deletions

File tree

api/src/main/java/com/getcode/network/client/Client_Transaction.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ fun Client.sendRemotely(
355355
}
356356

357357

358-
fun Client.requestFirstKinAirdrop(
358+
suspend fun Client.requestFirstKinAirdrop(
359359
owner: KeyPair,
360-
): Single<KinAmount> {
360+
): Result<KinAmount> {
361361
return transactionRepository.requestFirstKinAirdrop(owner)
362362
}
363363

api/src/main/java/com/getcode/network/repository/TransactionRepository.kt

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
4545
import kotlinx.coroutines.flow.StateFlow
4646
import kotlinx.coroutines.flow.asStateFlow
4747
import kotlinx.coroutines.flow.filterNot
48+
import kotlinx.coroutines.flow.first
4849
import kotlinx.coroutines.flow.firstOrNull
4950
import kotlinx.coroutines.flow.flowOn
5051
import kotlinx.coroutines.flow.map
@@ -343,7 +344,7 @@ class TransactionRepository @Inject constructor(
343344

344345
// TODO: potentially make this more generic in the event we introduce more airdrop types
345346
// that can be requested for
346-
fun requestFirstKinAirdrop(owner: Ed25519.KeyPair): Single<KinAmount> {
347+
suspend fun requestFirstKinAirdrop(owner: KeyPair): Result<KinAmount> {
347348
val request = TransactionService.AirdropRequest.newBuilder()
348349
.setOwner(owner.publicKeyBytes.toSolanaAccount())
349350
.setAirdropType(TransactionService.AirdropType.GET_FIRST_KIN)
@@ -354,25 +355,30 @@ class TransactionRepository @Inject constructor(
354355
}
355356
.build()
356357

357-
return transactionApi.airdrop(request).flatMap {
358-
when (it.result) {
359-
TransactionService.AirdropResponse.Result.OK -> {
360-
Single.just(KinAmount.fromProtoExchangeData(it.exchangeData))
361-
?: Single.error(IllegalStateException())
362-
}
358+
return runCatching {
359+
transactionApi.airdrop(request)
360+
.toFlowable()
361+
.asFlow()
362+
.flowOn(Dispatchers.IO)
363+
.map {
364+
when (it.result) {
365+
TransactionService.AirdropResponse.Result.OK -> {
366+
KinAmount.fromProtoExchangeData(it.exchangeData)
367+
}
363368

364-
TransactionService.AirdropResponse.Result.ALREADY_CLAIMED -> {
365-
Single.error(AirdropException.AlreadyClaimedException())
366-
}
369+
TransactionService.AirdropResponse.Result.ALREADY_CLAIMED -> {
370+
throw AirdropException.AlreadyClaimedException()
371+
}
367372

368-
TransactionService.AirdropResponse.Result.UNAVAILABLE -> {
369-
Single.error(AirdropException.UnavailableException())
370-
}
373+
TransactionService.AirdropResponse.Result.UNAVAILABLE -> {
374+
throw AirdropException.UnavailableException()
375+
}
371376

372-
else -> {
373-
Single.error(AirdropException.UnknownException())
374-
}
375-
}
377+
else -> {
378+
throw AirdropException.UnknownException()
379+
}
380+
}
381+
}.first()
376382
}
377383
}
378384

app/src/main/java/com/getcode/util/ModifierExt.kt

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,22 @@ import androidx.compose.runtime.remember
1414
import androidx.compose.ui.ExperimentalComposeUiApi
1515
import androidx.compose.ui.Modifier
1616
import androidx.compose.ui.composed
17+
import androidx.compose.ui.draw.drawBehind
18+
import androidx.compose.ui.draw.drawWithContent
19+
import androidx.compose.ui.geometry.Offset
20+
import androidx.compose.ui.graphics.BlendMode
1721
import androidx.compose.ui.graphics.Color
1822
import androidx.compose.ui.graphics.RectangleShape
1923
import androidx.compose.ui.graphics.Shape
20-
import androidx.compose.ui.input.pointer.pointerInput
2124
import androidx.compose.ui.input.pointer.pointerInteropFilter
25+
import androidx.compose.ui.layout.layout
2226
import androidx.compose.ui.layout.onPlaced
2327
import androidx.compose.ui.platform.LocalDensity
2428
import androidx.compose.ui.semantics.Role
2529
import androidx.compose.ui.unit.Dp
2630
import androidx.compose.ui.unit.DpSize
2731
import androidx.compose.ui.unit.dp
32+
import androidx.compose.ui.unit.offset
2833

2934
inline fun Modifier.addIf(
3035
predicate: Boolean,
@@ -56,7 +61,8 @@ fun Modifier.unboundedClickable(
5661
}
5762

5863

59-
fun Modifier.debugBounds(color: Color = Color.Magenta, shape: Shape = RectangleShape) = this.border(1.dp, color, shape)
64+
fun Modifier.debugBounds(color: Color = Color.Magenta, shape: Shape = RectangleShape) =
65+
this.border(1.dp, color, shape)
6066

6167
fun Modifier.rememberedClickable(
6268
enabled: Boolean = true,
@@ -122,4 +128,61 @@ fun Modifier.swallowClicks(onClick: () -> Unit = { }): Modifier =
122128
onClick()
123129
}
124130
true
125-
}
131+
}
132+
133+
/**
134+
* Draws circle with a solid [color] behind the content.
135+
*
136+
* @param color The color of the circle.
137+
* @param padding The padding to be applied externally to the circular shape. It determines the spacing between
138+
* the edge of the circle and the content inside.
139+
*
140+
* @return Combined [Modifier] that first draws the background circle and then centers the layout.
141+
*/
142+
fun Modifier.circleBackground(color: Color, padding: Dp): Modifier {
143+
val backgroundModifier = drawBehind {
144+
drawCircle(color, size.width / 2f, center = Offset(size.width / 2f, size.height / 2f))
145+
}
146+
147+
val layoutModifier = layout { measurable, constraints ->
148+
// Adjust the constraints by the padding amount
149+
val adjustedConstraints = constraints.offset(-padding.roundToPx())
150+
151+
// Measure the composable with the adjusted constraints
152+
val placeable = measurable.measure(adjustedConstraints)
153+
154+
// Get the current max dimension to assign width=height
155+
val currentHeight = placeable.height
156+
val currentWidth = placeable.width
157+
val newDiameter = maxOf(currentHeight, currentWidth) + padding.roundToPx() * 2
158+
159+
// Assign the dimension and the center position
160+
layout(newDiameter, newDiameter) {
161+
// Place the composable at the calculated position
162+
placeable.placeRelative(
163+
(newDiameter - currentWidth) / 2,
164+
(newDiameter - currentHeight) / 2
165+
)
166+
}
167+
}
168+
169+
return this then backgroundModifier then layoutModifier
170+
}
171+
172+
fun Modifier.punchRectangle(color: Color) = this.drawWithContent {
173+
drawRect(
174+
color,
175+
blendMode = BlendMode.Src
176+
)
177+
178+
drawContent()
179+
}
180+
181+
fun Modifier.punchCircle(color: Color) = this.drawWithContent {
182+
drawCircle(
183+
color,
184+
blendMode = BlendMode.Src
185+
)
186+
187+
drawContent()
188+
}

0 commit comments

Comments
 (0)