Add daily reward and fix event queue
continuous-integration/drone/push Build is passing Details

pull/5/head
avalin 9 months ago
parent fda26944d3
commit 527577677a

@ -112,7 +112,8 @@ fun BetConfirmationBottomSheetAnswer(
text = text.uppercase(),
color = contentColor ?: color,
style = AllInTheme.typography.h1,
fontSize = 40.sp,
fontSize = 30.sp,
textAlign = TextAlign.Center,
modifier = Modifier.align(Alignment.Center)
)

@ -0,0 +1,219 @@
package fr.iut.alldev.allin.ui.dailyReward
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.theme.AllInColorToken
import fr.iut.alldev.allin.theme.AllInTheme
@Composable
fun DailyRewardScreen(
amount: Int,
onDismiss: () -> Unit
) {
var hasOpened by remember { mutableStateOf(false) }
DailyRewardScreenContent(
amount = amount,
hasOpened = hasOpened
) {
if (hasOpened) {
onDismiss()
} else {
hasOpened = true
}
}
}
@Composable
fun DailyRewardScreenContent(
amount: Int,
hasOpened: Boolean,
onClick: () -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
val infiniteTransition = rememberInfiniteTransition(label = "")
val rotation by infiniteTransition.animateFloat(
initialValue = 3f,
targetValue = -3f,
animationSpec = infiniteRepeatable(
animation = tween(900),
repeatMode = RepeatMode.Reverse
), label = ""
)
val scale by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = .95f,
animationSpec = infiniteRepeatable(
animation = tween(900),
repeatMode = RepeatMode.Reverse
), label = ""
)
Column(
modifier = Modifier
.fillMaxSize()
.background(
Brush.verticalGradient(
0f to AllInColorToken.black.copy(alpha = .71f),
1f to AllInColorToken.black.copy(alpha = .97f)
)
)
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = onClick
),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(id = R.string.daily_reward_title),
style = AllInTheme.typography.h1,
fontSize = 20.sp,
color = AllInColorToken.white,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 48.dp)
)
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
.padding(horizontal = 48.dp),
contentAlignment = Alignment.Center
) {
Spacer(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
)
androidx.compose.animation.AnimatedVisibility(
visible = !hasOpened,
enter = fadeIn() + scaleIn(),
exit = fadeOut() + scaleOut(targetScale = 2f)
) {
Image(
painter = painterResource(id = R.drawable.daily_reward_1),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
.rotate(rotation)
.scale(scale)
)
}
androidx.compose.animation.AnimatedVisibility(
visible = hasOpened,
enter = fadeIn() + scaleIn(),
exit = fadeOut() + scaleOut(targetScale = 2f)
) {
Box(
contentAlignment = Alignment.BottomCenter
) {
Image(
painter = painterResource(id = R.drawable.daily_reward_2),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.rotate(rotation)
.scale(scale)
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.rotate(-rotation)
.scale(scale)
) {
Text(
text = "+$amount",
style = AllInTheme.typography.h1,
fontSize = 70.sp,
color = AllInColorToken.white
)
Icon(
painter = AllInTheme.icons.allCoins(),
tint = AllInColorToken.white,
contentDescription = null,
modifier = Modifier.size(48.dp)
)
}
}
}
}
Text(
text = stringResource(id = R.string.daily_reward_subtitle),
style = AllInTheme.typography.l1,
color = AllInColorToken.white,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 48.dp)
)
}
}
@Preview(showBackground = true)
@Composable
private fun DailyRewardScreenPreview() {
AllInTheme {
DailyRewardScreenContent(
amount = 125,
hasOpened = false,
onClick = {}
)
}
}
@Preview(showBackground = true)
@Composable
private fun DailyRewardScreenStep2Preview() {
AllInTheme {
DailyRewardScreenContent(
amount = 125,
hasOpened = true,
onClick = {}
)
}
}

@ -1,6 +1,9 @@
package fr.iut.alldev.allin.ui.main
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@ -33,12 +36,19 @@ import fr.iut.alldev.allin.ui.betStatus.vo.BetStatusBottomSheetBetDisplayer
import fr.iut.alldev.allin.ui.core.AllInLoading
import fr.iut.alldev.allin.ui.core.snackbar.AllInSnackbarVisualsImpl
import fr.iut.alldev.allin.ui.main.components.AllInScaffold
import fr.iut.alldev.allin.ui.main.event.DailyReward
import fr.iut.alldev.allin.ui.main.event.ToConfirmBet
import fr.iut.alldev.allin.ui.main.event.WonBet
import fr.iut.alldev.allin.ui.navigation.AllInDrawerNavHost
import fr.iut.alldev.allin.ui.navigation.Routes
import fr.iut.alldev.allin.ui.navigation.TopLevelDestination
import fr.iut.alldev.allin.ui.navigation.drawer.AllInDrawer
import fr.iut.alldev.allin.ui.navigation.popUpTo
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import timber.log.Timber
const val EVENT_DISMISS_DELAY_MS = 300L
private val topLevelDestinations = listOf(
TopLevelDestination.PublicBets,
@ -111,7 +121,6 @@ fun MainScreen(
}
)
AllInDrawer(
drawerState = drawerState,
destinations = topLevelDestinations,
@ -169,11 +178,53 @@ fun MainScreen(
}
}
events.firstOrNull()?.let {
it.Display(sheetState = eventBottomSheetState) {
mainViewModel.dismissedEvents += it
events.removeFirstOrNull()
when (val event = it) {
is ToConfirmBet -> {
Timber.d("ToConfirmBet")
event.Display(sheetState = eventBottomSheetState) {
mainViewModel.dismissedEvents += it
scope.launch {
eventBottomSheetState.hide()
delay(EVENT_DISMISS_DELAY_MS)
events.removeFirstOrNull()
}
}
}
is WonBet -> {
Timber.d("WonBet")
event.Display(sheetState = eventBottomSheetState) {
mainViewModel.dismissedEvents += it
scope.launch {
eventBottomSheetState.hide()
delay(EVENT_DISMISS_DELAY_MS)
events.removeFirstOrNull()
}
}
}
is DailyReward -> {
var dailyRewardVisible by remember { mutableStateOf(true) }
AnimatedVisibility(
visible = dailyRewardVisible,
enter = fadeIn(),
exit = fadeOut()
) {
(events.firstOrNull() as? DailyReward)?.let {
it.Display(
onDismiss = {
dailyRewardVisible = false
mainViewModel.dismissedEvents += it
scope.launch {
delay(EVENT_DISMISS_DELAY_MS)
events.removeFirstOrNull()
}
}
)
}
}
}
}
}
@ -191,6 +242,7 @@ fun MainScreen(
participateSheetVisibility = participateSheetVisibility,
setParticipateSheetVisibility = setParticipateSheetVisibility
)
AllInLoading(visible = loading)
}

@ -14,6 +14,7 @@ import fr.iut.alldev.allin.data.repository.UserRepository
import fr.iut.alldev.allin.keystore.AllInKeystoreManager
import fr.iut.alldev.allin.ui.core.snackbar.SnackbarType
import fr.iut.alldev.allin.ui.main.event.AllInEvent
import fr.iut.alldev.allin.ui.main.event.DailyReward
import fr.iut.alldev.allin.ui.main.event.ToConfirmBet
import fr.iut.alldev.allin.ui.main.event.WonBet
import kotlinx.coroutines.Dispatchers
@ -52,6 +53,8 @@ class MainViewModel @Inject constructor(
val token = keystoreManager.getTokenOrEmpty()
events.addAll(
buildList {
add(DailyReward(125))
addAll(betRepository.getToConfirm(token).map { bet ->
ToConfirmBet(
betDetail = bet,

@ -1,12 +1,3 @@
package fr.iut.alldev.allin.ui.main.event
import androidx.compose.material3.SheetState
import androidx.compose.runtime.Composable
sealed class AllInEvent {
@Composable
abstract fun Display(
sheetState: SheetState,
onDismiss: () -> Unit
)
}
sealed class AllInEvent

@ -0,0 +1,15 @@
package fr.iut.alldev.allin.ui.main.event
import androidx.compose.runtime.Composable
import fr.iut.alldev.allin.ui.dailyReward.DailyRewardScreen
data class DailyReward(private val amount: Int) : AllInEvent() {
@Composable
fun Display(onDismiss: () -> Unit) {
DailyRewardScreen(
amount = amount,
onDismiss = onDismiss
)
}
}

@ -10,7 +10,7 @@ data class ToConfirmBet(
private val onConfirm: (String) -> Unit
) : AllInEvent() {
@Composable
override fun Display(
fun Display(
sheetState: SheetState,
onDismiss: () -> Unit
) {

@ -11,7 +11,7 @@ data class WonBet(
private val betResult: BetResultDetail,
) : AllInEvent() {
@Composable
override fun Display(
fun Display(
sheetState: SheetState,
onDismiss: () -> Unit
) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

@ -143,4 +143,9 @@
<!--Ranking-->
<string name="ranking_title">Classement</string>
<!--Daily reward-->
<string name="daily_reward_title">Récompense quotidienne</string>
<string name="daily_reward_subtitle">Votre récompense quotidienne est débloquée tous les jours à 00:00 UTC et vous permets dobtenir entre 10 et 150 Allcoins.</string>
</resources>

@ -143,4 +143,8 @@
<!--Ranking-->
<string name="ranking_title">Ranking</string>
<!--Daily reward-->
<string name="daily_reward_title">Daily reward</string>
<string name="daily_reward_subtitle">Your daily reward is unlocked every day at 00:00 UTC and allows you to get between 10 and 150 Allcoins.</string>
</resources>

@ -336,7 +336,7 @@ class MockAllInApi : AllInApi {
response = listOf("The Monarchs", "Climate Change"),
createdBy = "User 1",
type = BetType.MATCH,
status = BetStatus.IN_PROGRESS,
status = BetStatus.CLOSING,
)
)

Loading…
Cancel
Save