parent
e2d119242c
commit
78b4ab2e05
@ -0,0 +1,110 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.ranking
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import fr.iut.alldev.allin.data.model.User
|
||||||
|
import fr.iut.alldev.allin.ui.ranking.components.RankingScreenContent
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RankingScreen() {
|
||||||
|
val users = remember { mockRanking }
|
||||||
|
|
||||||
|
RankingScreenContent(
|
||||||
|
users = users.sortedByDescending { it.coins }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mockRanking by lazy {
|
||||||
|
listOf(
|
||||||
|
User(
|
||||||
|
id = "1",
|
||||||
|
username = "Owen",
|
||||||
|
email = "",
|
||||||
|
coins = 8533
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "2",
|
||||||
|
username = "Dave",
|
||||||
|
email = "",
|
||||||
|
coins = 6942
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "3",
|
||||||
|
username = "Lucas",
|
||||||
|
email = "",
|
||||||
|
coins = 3333
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "4",
|
||||||
|
username = "Louison",
|
||||||
|
email = "",
|
||||||
|
coins = 1970
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "5",
|
||||||
|
username = "Imri",
|
||||||
|
email = "",
|
||||||
|
coins = 1
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "21",
|
||||||
|
username = "Owen",
|
||||||
|
email = "",
|
||||||
|
coins = 8533
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "22",
|
||||||
|
username = "Dave",
|
||||||
|
email = "",
|
||||||
|
coins = 6942
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "23",
|
||||||
|
username = "Lucas",
|
||||||
|
email = "",
|
||||||
|
coins = 3333
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "24",
|
||||||
|
username = "Louison",
|
||||||
|
email = "",
|
||||||
|
coins = 1970
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "25",
|
||||||
|
username = "Imri",
|
||||||
|
email = "",
|
||||||
|
coins = 1
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "31",
|
||||||
|
username = "Owen",
|
||||||
|
email = "",
|
||||||
|
coins = 8533
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "32",
|
||||||
|
username = "Dave",
|
||||||
|
email = "",
|
||||||
|
coins = 6942
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "33",
|
||||||
|
username = "Lucas",
|
||||||
|
email = "",
|
||||||
|
coins = 3333
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "34",
|
||||||
|
username = "Louison",
|
||||||
|
email = "",
|
||||||
|
coins = 1970
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "35",
|
||||||
|
username = "Imri",
|
||||||
|
email = "",
|
||||||
|
coins = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.ranking.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
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.data.model.User
|
||||||
|
import fr.iut.alldev.allin.theme.AllInTheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RankingScreenContent(
|
||||||
|
users: List<User>
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = PaddingValues(start = 24.dp, end = 24.dp, top = 18.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(11.dp),
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.ranking_title),
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
color = AllInTheme.colors.allInGrey,
|
||||||
|
fontSize = 24.sp,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.Bottom,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(11.dp)
|
||||||
|
) {
|
||||||
|
users.firstOrNull()?.let { first ->
|
||||||
|
RankingScreenFirst(
|
||||||
|
username = first.username,
|
||||||
|
coins = first.coins,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
users.getOrNull(1)?.let { second ->
|
||||||
|
RankingScreenSecond(
|
||||||
|
username = second.username,
|
||||||
|
coins = second.coins,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsIndexed(users.subList(1, users.size), key = { _, user -> user.id }) { idx, user ->
|
||||||
|
RankingScreenItem(
|
||||||
|
position = idx + 3,
|
||||||
|
username = user.username,
|
||||||
|
coins = user.coins
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.navigationBarsPadding())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun RankingScreenContentPreview() {
|
||||||
|
AllInTheme {
|
||||||
|
RankingScreenContent(
|
||||||
|
users = listOf(
|
||||||
|
User(
|
||||||
|
id = "1",
|
||||||
|
username = "Owen",
|
||||||
|
email = "",
|
||||||
|
coins = 8533
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "2",
|
||||||
|
username = "Dave",
|
||||||
|
email = "",
|
||||||
|
coins = 6942
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "3",
|
||||||
|
username = "Lucas",
|
||||||
|
email = "",
|
||||||
|
coins = 3333
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "4",
|
||||||
|
username = "Louison",
|
||||||
|
email = "",
|
||||||
|
coins = 1970
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = "5",
|
||||||
|
username = "Imri",
|
||||||
|
email = "",
|
||||||
|
coins = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.ranking.components
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
|
import fr.iut.alldev.allin.theme.AllInTheme
|
||||||
|
import fr.iut.alldev.allin.ui.core.AllInCard
|
||||||
|
import fr.iut.alldev.allin.ui.core.AllInCoinCount
|
||||||
|
import fr.iut.alldev.allin.ui.core.ProfilePicture
|
||||||
|
import racra.compose.smooth_corner_rect_library.AbsoluteSmoothCornerShape
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RankingScreenFirst(
|
||||||
|
username: String,
|
||||||
|
coins: Int,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Box(modifier) {
|
||||||
|
AllInCard(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
.padding(top = 35.dp),
|
||||||
|
shape = AbsoluteSmoothCornerShape(
|
||||||
|
cornerRadiusTL = 41.dp,
|
||||||
|
smoothnessAsPercentTL = 100,
|
||||||
|
cornerRadiusTR = 8.dp,
|
||||||
|
smoothnessAsPercentTR = 100,
|
||||||
|
cornerRadiusBR = 19.dp,
|
||||||
|
smoothnessAsPercentBR = 100,
|
||||||
|
cornerRadiusBL = 19.dp,
|
||||||
|
smoothnessAsPercentBL = 100
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(50.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = username,
|
||||||
|
color = AllInTheme.themeColors.onBackground,
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier.padding(8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
HorizontalDivider(color = AllInTheme.themeColors.border)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(AllInTheme.themeColors.background2)
|
||||||
|
.padding(16.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
AllInCoinCount(
|
||||||
|
amount = coins,
|
||||||
|
color = AllInTheme.colors.allInPurple,
|
||||||
|
size = 20
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProfilePicture(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(70.dp)
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
.zIndex(1f),
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
.padding(vertical = 55.dp)
|
||||||
|
.zIndex(500f)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(AllInTheme.colors.allInPurple)
|
||||||
|
.size(30.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "1",
|
||||||
|
color = AllInTheme.colors.white,
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier.padding(4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun RankingScreenFirstPreview() {
|
||||||
|
AllInTheme {
|
||||||
|
RankingScreenFirst(
|
||||||
|
username = "Username",
|
||||||
|
coins = 420
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.ranking.components
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import fr.iut.alldev.allin.theme.AllInTheme
|
||||||
|
import fr.iut.alldev.allin.ui.core.AllInCard
|
||||||
|
import fr.iut.alldev.allin.ui.core.AllInCoinCount
|
||||||
|
import fr.iut.alldev.allin.ui.core.ProfilePicture
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RankingScreenItem(
|
||||||
|
position: Int,
|
||||||
|
username: String,
|
||||||
|
coins: Int,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
AllInCard(
|
||||||
|
modifier = modifier,
|
||||||
|
radius = 8.dp
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 8.dp, vertical = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "$position",
|
||||||
|
color = AllInTheme.colors.allInPurple,
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
softWrap = false,
|
||||||
|
modifier = Modifier.size(width = 26.dp, height = 20.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
ProfilePicture(modifier = Modifier.size(38.dp))
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = username,
|
||||||
|
color = AllInTheme.themeColors.onBackground,
|
||||||
|
style = AllInTheme.typography.sm2,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
AllInCoinCount(
|
||||||
|
amount = coins,
|
||||||
|
color = AllInTheme.colors.allInPurple
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun RankingScreenItemPreview() {
|
||||||
|
AllInTheme {
|
||||||
|
RankingScreenItem(
|
||||||
|
position = 3,
|
||||||
|
username = "Username",
|
||||||
|
coins = 420
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun RankingScreenItemTenthPreview() {
|
||||||
|
AllInTheme {
|
||||||
|
RankingScreenItem(
|
||||||
|
position = 10,
|
||||||
|
username = "Username",
|
||||||
|
coins = 420
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.ranking.components
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
|
import fr.iut.alldev.allin.theme.AllInTheme
|
||||||
|
import fr.iut.alldev.allin.ui.core.AllInCard
|
||||||
|
import fr.iut.alldev.allin.ui.core.AllInCoinCount
|
||||||
|
import fr.iut.alldev.allin.ui.core.ProfilePicture
|
||||||
|
import racra.compose.smooth_corner_rect_library.AbsoluteSmoothCornerShape
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RankingScreenSecond(
|
||||||
|
username: String,
|
||||||
|
coins: Int,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Box(modifier) {
|
||||||
|
AllInCard(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
.padding(top = 28.dp),
|
||||||
|
shape = AbsoluteSmoothCornerShape(
|
||||||
|
cornerRadiusTL = 8.dp,
|
||||||
|
smoothnessAsPercentTL = 100,
|
||||||
|
cornerRadiusTR = 41.dp,
|
||||||
|
smoothnessAsPercentTR = 100,
|
||||||
|
cornerRadiusBR = 19.dp,
|
||||||
|
smoothnessAsPercentBR = 100,
|
||||||
|
cornerRadiusBL = 19.dp,
|
||||||
|
smoothnessAsPercentBL = 100
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(30.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = username,
|
||||||
|
color = AllInTheme.themeColors.onBackground,
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier.padding(8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
HorizontalDivider(color = AllInTheme.themeColors.border)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(AllInTheme.themeColors.background2)
|
||||||
|
.padding(16.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
AllInCoinCount(
|
||||||
|
amount = coins,
|
||||||
|
color = AllInTheme.colors.allInPurple,
|
||||||
|
size = 20
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProfilePicture(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(56.dp)
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
.zIndex(1f),
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
.padding(vertical = 44.dp)
|
||||||
|
.zIndex(500f)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(AllInTheme.colors.allInPurple)
|
||||||
|
.size(25.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "2",
|
||||||
|
color = AllInTheme.colors.white,
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier.padding(4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun RankingScreenSecondPreview() {
|
||||||
|
AllInTheme {
|
||||||
|
RankingScreenSecond(
|
||||||
|
username = "Username",
|
||||||
|
coins = 420
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.splash
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import fr.iut.alldev.allin.ui.splash.components.SplashScreenContent
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SplashScreen(
|
||||||
|
viewModel: SplashScreenViewModel = hiltViewModel(),
|
||||||
|
navigateToWelcomeScreen: () -> Unit,
|
||||||
|
navigateToDashboard: () -> Unit
|
||||||
|
) {
|
||||||
|
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
LaunchedEffect(key1 = state) {
|
||||||
|
(state as? SplashScreenViewModel.State.Loaded)?.let { loadedState ->
|
||||||
|
if (loadedState.isLoggedIn) {
|
||||||
|
navigateToDashboard()
|
||||||
|
} else {
|
||||||
|
navigateToWelcomeScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SplashScreenContent()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.splash
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import fr.iut.alldev.allin.data.repository.UserRepository
|
||||||
|
import fr.iut.alldev.allin.keystore.AllInKeystoreManager
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class SplashScreenViewModel @Inject constructor(
|
||||||
|
private val keystoreManager: AllInKeystoreManager,
|
||||||
|
private val userRepository: UserRepository
|
||||||
|
) : ViewModel() {
|
||||||
|
val state: StateFlow<State> by lazy {
|
||||||
|
flow {
|
||||||
|
delay(1_000L)
|
||||||
|
|
||||||
|
keystoreManager.getToken()?.let { token ->
|
||||||
|
runCatching {
|
||||||
|
userRepository
|
||||||
|
.login(token)
|
||||||
|
?.let { newToken ->
|
||||||
|
keystoreManager.putToken(newToken)
|
||||||
|
Timber.d("Put token $newToken")
|
||||||
|
}
|
||||||
|
}.onSuccess {
|
||||||
|
emit(State.Loaded(true))
|
||||||
|
}.onFailure {
|
||||||
|
emit(State.Loaded(false))
|
||||||
|
}
|
||||||
|
} ?: emit(State.Loaded(false))
|
||||||
|
|
||||||
|
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), State.Loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
keystoreManager.createKeystore()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface State {
|
||||||
|
data object Loading : State
|
||||||
|
data class Loaded(val isLoggedIn: Boolean) : State
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.splash.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import fr.iut.alldev.allin.R
|
||||||
|
import fr.iut.alldev.allin.theme.AllInTheme
|
||||||
|
import fr.iut.alldev.allin.ui.core.Icon
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SplashScreenContent() {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(AllInTheme.colors.allInLoginGradient),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.allin),
|
||||||
|
contentDescription = null,
|
||||||
|
tint = AllInTheme.colors.white,
|
||||||
|
modifier = Modifier.fillMaxSize(.25f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun SplashScreenContentPreview() {
|
||||||
|
AllInTheme {
|
||||||
|
SplashScreenContent()
|
||||||
|
}
|
||||||
|
}
|
@ -1,56 +1,15 @@
|
|||||||
package fr.iut.alldev.allin.ui.welcome
|
package fr.iut.alldev.allin.ui.welcome
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
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.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.text.ClickableText
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Brush
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
|
||||||
import fr.iut.alldev.allin.R
|
|
||||||
import fr.iut.alldev.allin.theme.AllInTheme
|
|
||||||
import fr.iut.alldev.allin.ui.core.AllInButton
|
|
||||||
import fr.iut.alldev.allin.ui.core.AllInLoading
|
|
||||||
import fr.iut.alldev.allin.ui.welcome.components.WelcomeScreenContent
|
import fr.iut.alldev.allin.ui.welcome.components.WelcomeScreenContent
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun WelcomeScreen(
|
fun WelcomeScreen(
|
||||||
navigateToRegister: () -> Unit,
|
navigateToRegister: () -> Unit,
|
||||||
navigateToLogin: () -> Unit,
|
navigateToLogin: () -> Unit,
|
||||||
navigateToDashboard: () -> Unit,
|
|
||||||
viewModel: WelcomeScreenViewModel = hiltViewModel()
|
|
||||||
) {
|
) {
|
||||||
val loading by remember { viewModel.loading }
|
|
||||||
|
|
||||||
LaunchedEffect(viewModel) {
|
|
||||||
viewModel.tryAutoLogin(navigateToDashboard)
|
|
||||||
}
|
|
||||||
|
|
||||||
WelcomeScreenContent(
|
WelcomeScreenContent(
|
||||||
navigateToRegister = navigateToRegister,
|
navigateToRegister = navigateToRegister,
|
||||||
navigateToLogin = navigateToLogin,
|
navigateToLogin = navigateToLogin
|
||||||
loading = loading
|
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,38 +0,0 @@
|
|||||||
package fr.iut.alldev.allin.ui.welcome
|
|
||||||
|
|
||||||
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
||||||
import fr.iut.alldev.allin.data.repository.UserRepository
|
|
||||||
import fr.iut.alldev.allin.keystore.AllInKeystoreManager
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@HiltViewModel
|
|
||||||
class WelcomeScreenViewModel @Inject constructor(
|
|
||||||
private val keystoreManager: AllInKeystoreManager,
|
|
||||||
private val userRepository: UserRepository
|
|
||||||
) : ViewModel() {
|
|
||||||
|
|
||||||
var loading = mutableStateOf(false)
|
|
||||||
|
|
||||||
fun tryAutoLogin(onSuccess: () -> Unit) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
loading.value = true
|
|
||||||
keystoreManager.createKeystore()
|
|
||||||
keystoreManager.getToken()?.let { token ->
|
|
||||||
runCatching {
|
|
||||||
userRepository
|
|
||||||
.login(token)
|
|
||||||
?.let { newToken ->
|
|
||||||
keystoreManager.putToken(newToken)
|
|
||||||
}
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue