From 9d7061fa62b1ba5d7a49a54a0e808eb31c77c5f4 Mon Sep 17 00:00:00 2001 From: avalin Date: Thu, 23 May 2024 09:46:04 +0200 Subject: [PATCH] Friends Screen + fix string resources format --- .../fr/iut/alldev/allin/vo/bet/BetVOTest.kt | 48 ++++- .../vo/bet/displayer/BetVOTestVisitor.kt | 9 +- .../java/fr/iut/alldev/allin/ext/StringExt.kt | 6 + .../fr/iut/alldev/allin/ui/bet/BetScreen.kt | 10 +- .../iut/alldev/allin/ui/bet/BetViewModel.kt | 5 +- .../allin/ui/bet/components/BetScreenCard.kt | 10 +- .../BetConfirmationBottomSheet.kt | 6 +- .../ui/betCreation/BetCreationViewModel.kt | 2 +- .../components/BetCreationScreenFriendLine.kt | 7 +- .../allin/ui/betHistory/BetCurrentScreen.kt | 4 +- .../allin/ui/betHistory/BetHistoryScreen.kt | 4 +- .../ui/betResult/BetResultBottomSheet.kt | 4 +- .../BetStatusParticipationAnswers.kt | 6 +- .../vo/BetStatusBottomSheetBetDisplayer.kt | 8 +- .../alldev/allin/ui/core/ProfilePicture.kt | 21 ++- .../allin/ui/core/bet/BetProfilePictureRow.kt | 57 +++--- .../alldev/allin/ui/friends/FriendsScreen.kt | 5 +- .../ui/friends/FriendsScreenViewModel.kt | 177 +++++------------- .../friends/components/FriendsScreenLine.kt | 2 + .../iut/alldev/allin/ui/main/MainViewModel.kt | 2 +- .../iut/alldev/allin/ui/navigation/NavHost.kt | 4 + .../drawer/components/DrawerHeader.kt | 2 + .../ui/preview/BetDetailPreviewProvider.kt | 4 +- .../allin/ui/preview/BetPreviewProvider.kt | 4 +- .../preview/BetWithStatusPreviewProvider.kt | 4 +- .../fr/iut/alldev/allin/ui/profile/Profile.kt | 9 - .../alldev/allin/ui/profile/ProfileScreen.kt | 32 ++++ .../allin/ui/profile/ProfileViewModel.kt | 42 +++++ .../profile/components/ProfileScreenHeader.kt | 105 +++++++++++ .../ranking/components/RankingScreenFirst.kt | 4 +- .../ranking/components/RankingScreenItem.kt | 6 +- .../ranking/components/RankingScreenSecond.kt | 4 +- .../iut/alldev/allin/vo/bet/BetDisplayer.kt | 6 +- .../fr/iut/alldev/allin/data/api/AllInApi.kt | 46 ++++- .../iut/alldev/allin/data/api/MockAllInApi.kt | 31 ++- .../iut/alldev/allin/data/api/model/ApiBet.kt | 4 +- .../alldev/allin/data/api/model/ApiFriend.kt | 8 + .../alldev/allin/data/di/RepositoryModule.kt | 6 + .../alldev/allin/data/model/bet/BetFactory.kt | 2 +- .../model/bet/{YesNoBet.kt => BinaryBet.kt} | 2 +- .../allin/data/repository/FriendRepository.kt | 9 + .../allin/data/repository/UserRepository.kt | 12 +- .../repository/impl/FriendRepositoryImpl.kt | 30 +++ .../repository/impl/UserRepositoryImpl.kt | 7 +- src/gradle/libs.versions.toml | 2 +- 45 files changed, 524 insertions(+), 254 deletions(-) delete mode 100644 src/app/src/main/java/fr/iut/alldev/allin/ui/profile/Profile.kt create mode 100644 src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileScreen.kt create mode 100644 src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileViewModel.kt create mode 100644 src/app/src/main/java/fr/iut/alldev/allin/ui/profile/components/ProfileScreenHeader.kt rename src/data/src/{dev => main}/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt (91%) create mode 100644 src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiFriend.kt rename src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/{YesNoBet.kt => BinaryBet.kt} (96%) create mode 100644 src/data/src/main/java/fr/iut/alldev/allin/data/repository/FriendRepository.kt create mode 100644 src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/FriendRepositoryImpl.kt diff --git a/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/BetVOTest.kt b/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/BetVOTest.kt index 088912f..f315c00 100644 --- a/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/BetVOTest.kt +++ b/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/BetVOTest.kt @@ -5,10 +5,11 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithTag import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest +import fr.iut.alldev.allin.data.model.User import fr.iut.alldev.allin.test.TestTags import fr.iut.alldev.allin.test.mock.Bets -import fr.iut.alldev.allin.ui.MainActivity import fr.iut.alldev.allin.theme.AllInTheme +import fr.iut.alldev.allin.ui.MainActivity import fr.iut.alldev.allin.vo.bet.displayer.BetTestDisplayer import org.junit.Before import org.junit.Rule @@ -33,13 +34,22 @@ class BetVOTest { } @Test - fun testDisplayer_shouldDisplayYesNoBetUI(){ + fun testDisplayer_shouldDisplayYesNoBetUI() { //Given + val currentUser = User( + id = "1", + username = "test", + email = "test@test.fr", + coins = 120 + ) //When composeTestRule.activity.setContent { - AllInTheme{ - displayer.DisplayBet(Bets.bets[0]) + AllInTheme { + displayer.DisplayBet( + Bets.bets[0], + currentUser + ) } } //Expect @@ -49,13 +59,22 @@ class BetVOTest { } @Test - fun testDisplayer_shouldDisplayMatchUI(){ + fun testDisplayer_shouldDisplayMatchUI() { //Given + val currentUser = User( + id = "1", + username = "test", + email = "test@test.fr", + coins = 120 + ) //When composeTestRule.activity.setContent { - AllInTheme{ - displayer.DisplayBet(Bets.bets[1]) + AllInTheme { + displayer.DisplayBet( + Bets.bets[1], + currentUser + ) } } //Expect @@ -65,13 +84,22 @@ class BetVOTest { } @Test - fun testDisplayer_shouldDisplayCustomBetUI(){ + fun testDisplayer_shouldDisplayCustomBetUI() { //Given + val currentUser = User( + id = "1", + username = "test", + email = "test@test.fr", + coins = 120 + ) //When composeTestRule.activity.setContent { - AllInTheme{ - displayer.DisplayBet(Bets.bets[2]) + AllInTheme { + displayer.DisplayBet( + Bets.bets[2], + currentUser + ) } } //Expect diff --git a/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/displayer/BetVOTestVisitor.kt b/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/displayer/BetVOTestVisitor.kt index 3acb14d..d075943 100644 --- a/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/displayer/BetVOTestVisitor.kt +++ b/src/app/src/androidTest/java/fr/iut/alldev/allin/vo/bet/displayer/BetVOTestVisitor.kt @@ -4,23 +4,24 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag +import fr.iut.alldev.allin.data.model.User import fr.iut.alldev.allin.data.model.bet.vo.BetDetail import fr.iut.alldev.allin.test.TestTags import fr.iut.alldev.allin.vo.bet.BetDisplayer class BetTestDisplayer : BetDisplayer { @Composable - override fun DisplayYesNoBet(betDetail: BetDetail) { - Text("This is a YesNo Bet", Modifier.testTag(TestTags.YES_NO_BET.tag)) + override fun DisplayBinaryBet(betDetail: BetDetail, currentUser: User) { + Text("This is a Binary Bet", Modifier.testTag(TestTags.YES_NO_BET.tag)) } @Composable - override fun DisplayMatchBet(betDetail: BetDetail) { + override fun DisplayMatchBet(betDetail: BetDetail, currentUser: User) { Text("This is a Match Bet", Modifier.testTag(TestTags.MATCH_BET.tag)) } @Composable - override fun DisplayCustomBet(betDetail: BetDetail) { + override fun DisplayCustomBet(betDetail: BetDetail, currentUser: User) { Text("This is a Custom Bet", Modifier.testTag(TestTags.CUSTOM_BET.tag)) } } \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ext/StringExt.kt b/src/app/src/main/java/fr/iut/alldev/allin/ext/StringExt.kt index 4d0bab2..c3526c1 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ext/StringExt.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ext/StringExt.kt @@ -18,4 +18,10 @@ fun String.verifyIsFloat(locale: Locale): String? { fun String.toFloatOrNull(locale: Locale): Float? { val format = DecimalFormat("0.##", DecimalFormatSymbols.getInstance(locale)) return format.parse(this)?.toFloat() +} + +fun String.asFallbackProfileUsername() = buildString { + this@asFallbackProfileUsername.trim().split("\\s+".toRegex(), limit = 2).forEach { + append(it.first().uppercase()) + } } \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetScreen.kt index 1bdaa63..cd71b15 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetScreen.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.pullRefresh import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -34,6 +33,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear import fr.iut.alldev.allin.data.ext.formatToTime import fr.iut.alldev.allin.data.model.bet.Bet @@ -50,10 +50,10 @@ fun BetScreen( viewModel: BetViewModel = hiltViewModel(), selectBet: (Bet, Boolean) -> Unit, ) { - val bets by viewModel.bets.collectAsState() - val filters by viewModel.filters.collectAsState() + val bets by viewModel.bets.collectAsStateWithLifecycle() + val filters by viewModel.filters.collectAsStateWithLifecycle() - val refreshing by viewModel.isRefreshing.collectAsState() + val refreshing by viewModel.isRefreshing.collectAsStateWithLifecycle() val pullRefreshState = rememberPullRefreshState(refreshing, { viewModel.refresh() }) val progressAnimation by animateFloatAsState(pullRefreshState.progress * 15, label = "") @@ -123,7 +123,7 @@ fun BetScreen( title = it.phrase, date = it.endRegisterDate.formatToMediumDateNoYear(), time = it.endRegisterDate.formatToTime(), - players = List(3) { null }, + players = emptyList(), // TODO : Players onClickParticipate = { selectBet(it, true) }, onClickCard = { selectBet(it, false) }, modifier = Modifier diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetViewModel.kt index d3d5da4..179234f 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetViewModel.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/BetViewModel.kt @@ -24,8 +24,7 @@ class BetViewModel @Inject constructor( ) : ViewModel() { private val _isRefreshing by lazy { MutableStateFlow(false) } - val isRefreshing: StateFlow - get() = _isRefreshing.asStateFlow() + val isRefreshing: StateFlow get() = _isRefreshing.asStateFlow() private val _bets: MutableStateFlow> by lazy { MutableStateFlow(emptyList()) @@ -45,7 +44,7 @@ class BetViewModel @Inject constructor( MutableStateFlow(BetFilter.entries) } - val filters by lazy { _filters.asStateFlow() } + val filters get() = _filters.asStateFlow() init { viewModelScope.launch { diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/components/BetScreenCard.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/components/BetScreenCard.kt index 6873a22..6efae6e 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/components/BetScreenCard.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/bet/components/BetScreenCard.kt @@ -15,12 +15,12 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import fr.iut.alldev.allin.R +import fr.iut.alldev.allin.data.model.User import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.AllInBouncyCard import fr.iut.alldev.allin.ui.core.RainbowButton @@ -35,7 +35,7 @@ fun BetScreenCard( title: String, date: String, time: String, - players: List, + players: List, modifier: Modifier = Modifier, onClickParticipate: () -> Unit, onClickCard: () -> Unit, @@ -71,7 +71,7 @@ fun BetScreenCard( .padding(7.dp), verticalAlignment = Alignment.CenterVertically ) { - BetProfilePictureRow(pictures = players) + BetProfilePictureRow(pictures = players.map { it.username to null }) Spacer(modifier = Modifier.width(12.dp)) Text( text = pluralStringResource( @@ -103,7 +103,9 @@ private fun BetScreenCardPreview() { title = "Emre va réussir son TP de CI/CD mercredi?", date = "12 Sept.", time = "13:00", - players = List(3) { null }, + players = listOf( + User(id = "", username = "Lucas D", email = "", coins = 0), + ), onClickParticipate = {}, onClickCard = {} ) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betConfirmation/BetConfirmationBottomSheet.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betConfirmation/BetConfirmationBottomSheet.kt index e967307..a094bd0 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betConfirmation/BetConfirmationBottomSheet.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betConfirmation/BetConfirmationBottomSheet.kt @@ -48,7 +48,7 @@ import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail import fr.iut.alldev.allin.data.model.bet.vo.BetDetail import fr.iut.alldev.allin.ext.formatToSimple @@ -153,7 +153,7 @@ fun ConfirmationAnswers( when (val bet = betDetail.bet) { is CustomBet -> bet.possibleAnswers is MatchBet -> listOf(bet.nameTeam1, bet.nameTeam2) - is YesNoBet -> listOf(YES_VALUE, NO_VALUE) + is BinaryBet -> listOf(YES_VALUE, NO_VALUE) } } @@ -295,7 +295,7 @@ private fun BetConfirmationBottomSheetContentPreview() { AllInTheme { BetConfirmationBottomSheetContent( betDetail = BetDetail( - bet = YesNoBet( + bet = BinaryBet( id = "1", theme = "Theme", phrase = "Phrase", diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt index 48c3421..cd9398b 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt @@ -96,7 +96,7 @@ class BetCreationViewModel @Inject constructor( if (!hasError.value) { try { - userRepository.currentUser.value?.let { currentUser -> + userRepository.currentUserState.value?.let { currentUser -> val bet = BetFactory.createBet( id = "", betType = selectedBetType.value, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/components/BetCreationScreenFriendLine.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/components/BetCreationScreenFriendLine.kt index 4cde21f..ed00e1f 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/components/BetCreationScreenFriendLine.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/components/BetCreationScreenFriendLine.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -16,6 +15,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import fr.iut.alldev.allin.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.AllInCoinCount @@ -45,7 +45,10 @@ fun BetCreationScreenFriendLine( checked = isSelected, modifier = Modifier.padding(end = 7.dp) ) - ProfilePicture(modifier = Modifier.size(25.dp)) + ProfilePicture( + fallback = username.asFallbackProfileUsername(), + size = 25.dp + ) Text( text = username, fontWeight = FontWeight.Bold, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetCurrentScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetCurrentScreen.kt index 0fea3ae..fff46cb 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetCurrentScreen.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetCurrentScreen.kt @@ -1,10 +1,10 @@ package fr.iut.alldev.allin.ui.betHistory import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import fr.iut.alldev.allin.R import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear import fr.iut.alldev.allin.data.ext.formatToTime @@ -16,7 +16,7 @@ fun BetCurrentScreen( selectBet: (Bet, Boolean) -> Unit, viewModel: BetCurrentViewModel = hiltViewModel() ) { - val bets by viewModel.bets.collectAsState() + val bets by viewModel.bets.collectAsStateWithLifecycle() GenericHistory( title = stringResource(id = R.string.bet_history_current_title), bets = bets, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetHistoryScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetHistoryScreen.kt index c9a0538..34889e8 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetHistoryScreen.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betHistory/BetHistoryScreen.kt @@ -1,10 +1,10 @@ package fr.iut.alldev.allin.ui.betHistory import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import fr.iut.alldev.allin.R import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear import fr.iut.alldev.allin.data.ext.formatToTime @@ -16,7 +16,7 @@ fun BetHistoryScreen( selectBet: (Bet, Boolean) -> Unit, viewModel: BetHistoryViewModel = hiltViewModel() ) { - val bets by viewModel.bets.collectAsState() + val bets by viewModel.bets.collectAsStateWithLifecycle() GenericHistory( title = stringResource(id = R.string.bet_history_title), bets = bets, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt index 7b793c1..62e64b5 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt @@ -21,7 +21,7 @@ import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear import fr.iut.alldev.allin.data.ext.formatToTime import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.BetStatus -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.betResult.components.BetResultBottomSheetBetCard @@ -133,7 +133,7 @@ private fun BetResultBottomSheetContentPreview() { BetResultBottomSheetContent( username = "Pseudo", coinAmount = 3976, - bet = YesNoBet( + bet = BinaryBet( id = "1", theme = "Theme", phrase = "Phrase", diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt index 2949846..b06e00e 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt @@ -25,7 +25,7 @@ import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import fr.iut.alldev.allin.data.model.bet.vo.BetDetail import fr.iut.alldev.allin.ext.formatToSimple import fr.iut.alldev.allin.theme.AllInColorToken @@ -77,7 +77,7 @@ fun BetDetail.getParticipationAnswers(): List<@Composable RowScope.() -> Unit> { } } - is YesNoBet -> buildList { + is BinaryBet -> buildList { add { this@getParticipationAnswers.getAnswerOfResponse(YES_VALUE)?.let { ParticipationAnswerLine( @@ -144,7 +144,7 @@ fun Bet.getAnswerFromParticipationIdx(idx: Int) = else -> "" } - is YesNoBet -> when (idx) { + is BinaryBet -> when (idx) { 0 -> YES_VALUE 1 -> NO_VALUE else -> "" diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt index c5fb708..83ae14b 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt @@ -55,6 +55,7 @@ import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail import fr.iut.alldev.allin.data.model.bet.vo.BetDetail +import fr.iut.alldev.allin.ext.asFallbackProfileUsername import fr.iut.alldev.allin.ext.asPaddingValues import fr.iut.alldev.allin.ext.bottomSheetNavigationBarsInsets import fr.iut.alldev.allin.ext.formatToSimple @@ -295,7 +296,7 @@ class BetStatusBottomSheetBetDisplayer( } @Composable - override fun DisplayYesNoBet(betDetail: BetDetail, currentUser: User) { + override fun DisplayBinaryBet(betDetail: BetDetail, currentUser: User) { DisplayBetDail( betDetail = betDetail, currentUser = currentUser, @@ -390,7 +391,10 @@ fun BetStatusParticipant( horizontalArrangement = Arrangement.spacedBy(7.dp), verticalAlignment = Alignment.CenterVertically ) { - ProfilePicture(modifier = Modifier.size(25.dp)) + ProfilePicture( + fallback = username.asFallbackProfileUsername(), + size = 25.dp + ) Text( text = username, fontWeight = FontWeight.Bold, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/ProfilePicture.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/ProfilePicture.kt index 3dcefb6..af2b3bd 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/ProfilePicture.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/ProfilePicture.kt @@ -6,17 +6,17 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.PhotoCamera import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon +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.graphics.painter.Painter +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource +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.dp @@ -26,6 +26,7 @@ import fr.iut.alldev.allin.theme.AllInTheme @Composable fun ProfilePicture( + fallback: String, modifier: Modifier = Modifier, image: Painter? = null, borderWidth: Dp? = null, @@ -49,13 +50,14 @@ fun ProfilePicture( .clip(shape) ) } ?: run { - Icon( - imageVector = Icons.Default.PhotoCamera, - tint = AllInColorToken.white, - contentDescription = null, + Text( + text = fallback, + style = AllInTheme.typography.p2, + textAlign = TextAlign.Center, + fontSize = with(LocalDensity.current) { (size / 2).toSp() }, + color = AllInColorToken.white, modifier = Modifier .align(Alignment.Center) - .fillMaxSize(0.5f) .clip(shape) ) } @@ -68,7 +70,7 @@ fun ProfilePicture( @Composable private fun ProfilePictureDefaultPreview() { AllInTheme { - ProfilePicture() + ProfilePicture("LS") } } @@ -77,6 +79,7 @@ private fun ProfilePictureDefaultPreview() { private fun ProfilePicturePreview() { AllInTheme { ProfilePicture( + fallback = "LS", image = painterResource(id = R.drawable.money_with_wings) ) } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/bet/BetProfilePictureRow.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/bet/BetProfilePictureRow.kt index ed1ef5a..e0ae775 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/bet/BetProfilePictureRow.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/bet/BetProfilePictureRow.kt @@ -1,6 +1,7 @@ package fr.iut.alldev.allin.ui.core.bet import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable @@ -13,24 +14,22 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import fr.iut.alldev.allin.R -import fr.iut.alldev.allin.ui.core.ProfilePicture +import fr.iut.alldev.allin.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInTheme +import fr.iut.alldev.allin.ui.core.ProfilePicture @Composable fun BetProfilePictureRow( - pictures: List, - maxLength: Int = 5, - modifier: Modifier = Modifier + pictures: List>, + modifier: Modifier = Modifier, + maxLength: Int = 5 ) { - val nRepeat = remember{ - if (pictures.size > maxLength) maxLength else pictures.size - } + val nRepeat = remember{ pictures.size.coerceAtMost(maxLength) } - Box( - modifier.width((nRepeat*17).dp) - ){ - pictures.forEachIndexed { index, painter -> + Box(modifier.width((35 + (nRepeat - 1) * 17).dp)){ + pictures.take(nRepeat).forEachIndexed { index, (username, painter) -> ProfilePicture( + fallback = username.asFallbackProfileUsername(), image = painter, size = 35.dp, modifier = Modifier @@ -46,24 +45,34 @@ fun BetProfilePictureRow( @Composable private fun BetProfilePictureRowPreview() { AllInTheme { - BetProfilePictureRow(pictures = listOf( - painterResource(id = R.drawable.money_with_wings), - null, - painterResource(id = R.drawable.money_with_wings) - )) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + BetProfilePictureRow( + pictures = listOf("lucas" to null) + ) + } } } @Preview @Composable private fun BetProfilePictureRowMaxPreview() { AllInTheme { - BetProfilePictureRow(pictures = listOf( - painterResource(id = R.drawable.money_with_wings), - null, - painterResource(id = R.drawable.money_with_wings), - null, - painterResource(id = R.drawable.money_with_wings), - null - )) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + BetProfilePictureRow( + pictures = listOf( + "lucas" to painterResource(id = R.drawable.money_with_wings), + "lucas" to null, + "lucas" to painterResource(id = R.drawable.money_with_wings), + "lucas" to null, + "lucas" to painterResource(id = R.drawable.money_with_wings), + "lucas" to null + ) + ) + } } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreen.kt index 9910f20..fa7da99 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreen.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import fr.iut.alldev.allin.data.model.User import fr.iut.alldev.allin.ui.core.AllInLoading import fr.iut.alldev.allin.ui.friends.components.FriendsScreenContent @@ -15,7 +16,7 @@ fun FriendsScreen( viewModel: FriendsScreenViewModel = hiltViewModel() ) { var search by remember { viewModel.search } - val state by remember { viewModel.state } + val state by viewModel.state.collectAsStateWithLifecycle() when (val s = state) { is FriendsScreenViewModel.State.Loaded -> { @@ -33,8 +34,10 @@ fun FriendsScreen( setSearch = { search = it }, onToggleDeleteFriend = { deleted = if (deleted.contains(it)) { + viewModel.addFriend(it.username) deleted - it } else { + viewModel.removeFriend(it.username) deleted + it } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreenViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreenViewModel.kt index 04c5c26..0b35979 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreenViewModel.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/FriendsScreenViewModel.kt @@ -5,150 +5,69 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import fr.iut.alldev.allin.data.model.User +import fr.iut.alldev.allin.data.repository.FriendRepository +import fr.iut.alldev.allin.keystore.AllInKeystoreManager +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject @HiltViewModel class FriendsScreenViewModel @Inject constructor( + private val friendRepository: FriendRepository, + private val keystoreManager: AllInKeystoreManager ) : ViewModel() { val search by lazy { mutableStateOf("") } - val state by lazy { mutableStateOf(State.Loading) } + private val _state by lazy { MutableStateFlow(State.Loading) } + val state get() = _state.asStateFlow() init { viewModelScope.launch { - state.value = State.Loaded(mockFriends) + try { + _state.emit( + State.Loaded( + friends = friendRepository.getFriends( + token = keystoreManager.getTokenOrEmpty() + ) + ) + ) + } catch (e: Exception) { + Timber.e(e) + } } } - sealed class State { - data object Loading: State() + fun addFriend(username: String) { + viewModelScope.launch { + try { + friendRepository.add( + token = keystoreManager.getTokenOrEmpty(), + username = username + ) + } catch (e: Exception) { + Timber.e(e) + } + } + } + + fun removeFriend(username: String) { + viewModelScope.launch { + try { + friendRepository.remove( + token = keystoreManager.getTokenOrEmpty(), + username = username + ) + } catch (e: Exception) { + Timber.e(e) + } + } + } - data class Loaded(val friends: List): State() + sealed interface State { + data object Loading : State + data class Loaded(val friends: List) : State } } -private val mockFriends 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 = "12", - username = "Owen", - email = "", - coins = 8533 - ), - User( - id = "22", - username = "Dave", - email = "", - coins = 6942 - ), - User( - id = "32", - username = "Lucas", - email = "", - coins = 3333 - ), - User( - id = "42", - username = "Louison", - email = "", - coins = 1970 - ), - User( - id = "52", - username = "Imri", - email = "", - coins = 1 - ), - User( - id = "13", - username = "Owen", - email = "", - coins = 8533 - ), - User( - id = "23", - username = "Dave", - email = "", - coins = 6942 - ), - User( - id = "33", - username = "Lucas", - email = "", - coins = 3333 - ), - User( - id = "43", - username = "Louison", - email = "", - coins = 1970 - ), - User( - id = "53", - username = "Imri", - email = "", - coins = 1 - ), - User( - id = "14", - username = "Owen", - email = "", - coins = 8533 - ), - User( - id = "24", - username = "Dave", - email = "", - coins = 6942 - ), - User( - id = "34", - username = "Lucas", - email = "", - coins = 3333 - ), - User( - id = "44", - username = "Louison", - email = "", - coins = 1970 - ), - User( - id = "54", - username = "Imri", - email = "", - coins = 1 - ) - ) -} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/components/FriendsScreenLine.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/components/FriendsScreenLine.kt index c303048..79b6247 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/components/FriendsScreenLine.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/friends/components/FriendsScreenLine.kt @@ -13,6 +13,7 @@ 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.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.AllInButton @@ -31,6 +32,7 @@ fun FriendsScreenLine( horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ProfilePicture( + fallback = username.asFallbackProfileUsername(), size = 50.dp ) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt index ec82643..5c9f5b7 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt @@ -32,7 +32,7 @@ class MainViewModel @Inject constructor( var loading = mutableStateOf(false) - val currentUser = userRepository.currentUser + val currentUser = userRepository.currentUserState val selectedBet = mutableStateOf(null) val dismissedEvents = mutableStateListOf() val events = mutableStateListOf() diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/NavHost.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/NavHost.kt index 236d8d0..d2c5be3 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/NavHost.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/NavHost.kt @@ -48,6 +48,10 @@ object Routes { const val RANKING = "RANKING" } +object Arguments { + const val USER_ID = "USER_ID" +} + private val fadingRoutes get() = listOf( Routes.WELCOME, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/drawer/components/DrawerHeader.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/drawer/components/DrawerHeader.kt index 6d823a5..5e4a6fb 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/drawer/components/DrawerHeader.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/navigation/drawer/components/DrawerHeader.kt @@ -17,6 +17,7 @@ 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.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.ProfilePicture @@ -34,6 +35,7 @@ fun DrawerHeader( horizontalAlignment = Alignment.CenterHorizontally ) { ProfilePicture( + fallback = username.asFallbackProfileUsername(), borderWidth = 1.dp ) Spacer(modifier = Modifier.height(12.dp)) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt index 6a403f9..b70f16e 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt @@ -6,7 +6,7 @@ import fr.iut.alldev.allin.data.model.bet.MatchBet import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.Participation import fr.iut.alldev.allin.data.model.bet.YES_VALUE -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail import fr.iut.alldev.allin.data.model.bet.vo.BetDetail @@ -60,7 +60,7 @@ class BetDetailPreviewProvider : PreviewParameterProvider { odds = 2.0f ) ) - is YesNoBet -> listOf( + is BinaryBet -> listOf( BetAnswerDetail( response = YES_VALUE, totalStakes = 300, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt index 4be8aed..c784f91 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt @@ -5,12 +5,12 @@ import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.BetStatus import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import java.time.ZonedDateTime class BetPreviewProvider : PreviewParameterProvider { override val values = sequenceOf( - YesNoBet( + BinaryBet( id = "1", theme = "Theme", phrase = "Phrase", diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt index 3cfab61..e682c4e 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt @@ -5,14 +5,14 @@ import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.BetStatus import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import java.time.ZonedDateTime class BetWithStatusPreviewProvider : PreviewParameterProvider { override val values = BetStatus.entries.asSequence().flatMap { status -> sequenceOf( - YesNoBet( + BinaryBet( id = "1", theme = "Theme", phrase = "Phrase", diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/Profile.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/Profile.kt deleted file mode 100644 index 09c3f88..0000000 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/Profile.kt +++ /dev/null @@ -1,9 +0,0 @@ -package fr.iut.alldev.allin.ui.profile - -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable - -@Composable -fun Profile(){ - Text(text = "PROFILE") -} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileScreen.kt new file mode 100644 index 0000000..8028cdc --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileScreen.kt @@ -0,0 +1,32 @@ +package fr.iut.alldev.allin.ui.profile + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import fr.iut.alldev.allin.ui.profile.components.ProfileScreenHeader + +@Composable +fun ProfileScreen( + viewModel: ProfileViewModel = hiltViewModel() +) { + val state by viewModel.state.collectAsStateWithLifecycle() + + Column { + when (val s = state) { + is ProfileViewModel.State.Loaded -> { + ProfileScreenHeader( + username = s.user.username, + totalBets = 333, + bestWin = 365, + friends = 3 + ) + } + + ProfileViewModel.State.Loading -> { + + } + } + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileViewModel.kt new file mode 100644 index 0000000..f0078d2 --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/ProfileViewModel.kt @@ -0,0 +1,42 @@ +package fr.iut.alldev.allin.ui.profile + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import fr.iut.alldev.allin.data.model.User +import fr.iut.alldev.allin.data.repository.UserRepository +import fr.iut.alldev.allin.ui.navigation.Arguments +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ProfileViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, + private val userRepository: UserRepository +) : ViewModel() { + private val userId: String? = savedStateHandle[Arguments.USER_ID] + + private val _state by lazy { MutableStateFlow(State.Loading) } + val state: StateFlow get() = _state.asStateFlow() + + init { + viewModelScope.launch { + + userRepository.currentUserState.value?.let { currentUser -> + if (userId == currentUser.id) { + _state.emit(State.Loaded(currentUser)) + } + } + + } + } + + sealed interface State { + data object Loading : State + data class Loaded(val user: User) : State + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/components/ProfileScreenHeader.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/components/ProfileScreenHeader.kt new file mode 100644 index 0000000..275cbe9 --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/profile/components/ProfileScreenHeader.kt @@ -0,0 +1,105 @@ +package fr.iut.alldev.allin.ui.profile.components + +import android.content.res.Configuration +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +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.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.ext.asFallbackProfileUsername +import fr.iut.alldev.allin.theme.AllInTheme +import fr.iut.alldev.allin.ui.core.ProfilePicture + +@Composable +fun ProfileScreenHeader( + username: String, + totalBets: Int, + bestWin: Int, + friends: Int +) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + ProfilePicture( + fallback = username.asFallbackProfileUsername(), + size = 68.dp + ) + Column( + verticalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier.height(68.dp) + ) { + Text( + text = username, + style = AllInTheme.typography.h2, + color = AllInTheme.colors.onMainSurface, + fontSize = 20.sp + ) + Row( + horizontalArrangement = Arrangement.spacedBy(20.dp) + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text( + text = totalBets.toString(), + style = AllInTheme.typography.h1, + color = AllInTheme.colors.onMainSurface, + fontSize = 14.sp, + ) + Text( + text = stringResource(id = R.string.drawer_bets), + style = AllInTheme.typography.p1, + color = AllInTheme.colors.onBackground2 + ) + } + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text( + text = bestWin.toString(), + style = AllInTheme.typography.h1, + color = AllInTheme.colors.onMainSurface, + fontSize = 14.sp + ) + Text( + text = stringResource(id = R.string.drawer_best_win), + style = AllInTheme.typography.p1, + color = AllInTheme.colors.onBackground2 + ) + } + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text( + text = friends.toString(), + style = AllInTheme.typography.h1, + color = AllInTheme.colors.onMainSurface, + fontSize = 14.sp + ) + Text( + text = stringResource(id = R.string.drawer_friends), + style = AllInTheme.typography.p1, + color = AllInTheme.colors.onBackground2 + ) + } + } + } + } +} + +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun ProfileScreenHeaderPreview() { + AllInTheme { + ProfileScreenHeader( + username = "User 1", + totalBets = 12, + bestWin = 365, + friends = 5 + ) + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenFirst.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenFirst.kt index 5491a8a..87708fd 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenFirst.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenFirst.kt @@ -22,6 +22,7 @@ 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.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.AllInCard @@ -87,8 +88,9 @@ fun RankingScreenFirst( } } ProfilePicture( + fallback = username.asFallbackProfileUsername(), + size = 70.dp, modifier = Modifier - .size(70.dp) .align(Alignment.TopCenter) .zIndex(1f), ) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenItem.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenItem.kt index 4bf3308..149bf85 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenItem.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenItem.kt @@ -15,6 +15,7 @@ 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.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.AllInCard @@ -48,7 +49,10 @@ fun RankingScreenItem( modifier = Modifier.size(width = 26.dp, height = 20.dp) ) - ProfilePicture(modifier = Modifier.size(38.dp)) + ProfilePicture( + fallback = username.asFallbackProfileUsername(), + size = 38.dp + ) Spacer(modifier = Modifier.width(8.dp)) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenSecond.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenSecond.kt index 2f4f9e5..d654126 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenSecond.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/ranking/components/RankingScreenSecond.kt @@ -22,6 +22,7 @@ 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.ext.asFallbackProfileUsername import fr.iut.alldev.allin.theme.AllInColorToken import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.AllInCard @@ -87,8 +88,9 @@ fun RankingScreenSecond( } } ProfilePicture( + fallback = username.asFallbackProfileUsername(), + size = 56.dp, modifier = Modifier - .size(56.dp) .align(Alignment.TopCenter) .zIndex(1f), ) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt b/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt index fddf2b6..75744b9 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt @@ -2,9 +2,9 @@ package fr.iut.alldev.allin.vo.bet import androidx.compose.runtime.Composable import fr.iut.alldev.allin.data.model.User +import fr.iut.alldev.allin.data.model.bet.BinaryBet import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet -import fr.iut.alldev.allin.data.model.bet.YesNoBet import fr.iut.alldev.allin.data.model.bet.vo.BetDetail interface BetDisplayer { @@ -13,12 +13,12 @@ interface BetDisplayer { when (betDetail.bet) { is CustomBet -> DisplayCustomBet(betDetail, currentUser) is MatchBet -> DisplayMatchBet(betDetail, currentUser) - is YesNoBet -> DisplayYesNoBet(betDetail, currentUser) + is BinaryBet -> DisplayBinaryBet(betDetail, currentUser) } } @Composable - fun DisplayYesNoBet(betDetail: BetDetail, currentUser: User) + fun DisplayBinaryBet(betDetail: BetDetail, currentUser: User) @Composable fun DisplayMatchBet(betDetail: BetDetail, currentUser: User) diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt index be48324..4d6067b 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt @@ -3,6 +3,7 @@ package fr.iut.alldev.allin.data.api import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.RequestBet import fr.iut.alldev.allin.data.api.model.RequestBetFilters +import fr.iut.alldev.allin.data.api.model.RequestFriend import fr.iut.alldev.allin.data.api.model.RequestParticipation import fr.iut.alldev.allin.data.api.model.RequestUser import fr.iut.alldev.allin.data.api.model.ResponseBet @@ -26,6 +27,9 @@ interface AllInApi { this.toRequestBody("text/plain".toMediaTypeOrNull()) } + // USERS + // --------------------- + @POST("users/login") suspend fun login(@Body body: CheckUser): ResponseUser @@ -35,12 +39,33 @@ interface AllInApi { @GET("users/token") suspend fun login(@Header("Authorization") token: String): ResponseUser - @POST("bets/add") - suspend fun createBet(@Header("Authorization") token: String, @Body body: RequestBet) - @GET("users/gift") suspend fun dailyGift(@Header("Authorization") token: String): Int + // FRIENDS + // --------------------- + + @GET("friends/add") + suspend fun getFriends(@Header("Authorization") token: String): List + + @POST("friends/add") + suspend fun addFriend( + @Header("Authorization") token: String, + @Body request: RequestFriend + ) + + @POST("friends/delete") + suspend fun deleteFriend( + @Header("Authorization") token: String, + @Body request: RequestFriend + ) + + // BETS + // --------------------- + + @POST("bets/add") + suspend fun createBet(@Header("Authorization") token: String, @Body body: RequestBet) + @POST("bets/gets") suspend fun getAllBets( @Header("Authorization") token: String, @@ -57,12 +82,6 @@ interface AllInApi { @Body value: RequestBody ) - @GET("betdetail/get/{id}") - suspend fun getBet( - @Header("Authorization") token: String, - @Path("id") id: String - ): ResponseBetDetail - @GET("bets/current") suspend fun getBetCurrent( @Header("Authorization") token: String @@ -78,6 +97,15 @@ interface AllInApi { @Header("Authorization") token: String ): List + @GET("betdetail/get/{id}") + suspend fun getBet( + @Header("Authorization") token: String, + @Path("id") id: String + ): ResponseBetDetail + + // PARTICIPATIONS + // --------------------- + @POST("participations/add") suspend fun participateToBet( @Header("Authorization") token: String, diff --git a/src/data/src/dev/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt similarity index 91% rename from src/data/src/dev/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt rename to src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt index edac2dd..0f7a228 100644 --- a/src/data/src/dev/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt @@ -3,6 +3,7 @@ package fr.iut.alldev.allin.data.api import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.RequestBet import fr.iut.alldev.allin.data.api.model.RequestBetFilters +import fr.iut.alldev.allin.data.api.model.RequestFriend import fr.iut.alldev.allin.data.api.model.RequestParticipation import fr.iut.alldev.allin.data.api.model.RequestUser import fr.iut.alldev.allin.data.api.model.ResponseBet @@ -28,7 +29,6 @@ import java.util.UUID class MockAllInApiException(override val message: String?) : Exception() class MockAllInApi : AllInApi { - init { CoroutineScope(Dispatchers.Default).launch { while (true) { @@ -135,6 +135,27 @@ class MockAllInApi : AllInApi { } else throw MockAllInApiException("Gift already taken today") } + override suspend fun getFriends(token: String): List { + val user = getUserFromToken(token) ?: throw MockAllInApiException("Invalid login/password.") + return mockFriends + .filter { it.first == user.first.id } + .mapNotNull { mockUsers.find { usr -> usr.first.id == it.second }?.first } + } + + override suspend fun addFriend(token: String, request: RequestFriend) { + val user = getUserFromToken(token) ?: throw MockAllInApiException("Invalid login/password.") + val requestUser = + mockUsers.find { it.first.username == request.username } ?: throw MockAllInApiException("Requested user not found") + mockFriends.add(user.first.id to requestUser.first.id) + } + + override suspend fun deleteFriend(token: String, request: RequestFriend) { + val user = getUserFromToken(token) ?: throw MockAllInApiException("Invalid login/password.") + val requestUser = + mockUsers.find { it.first.username == request.username } ?: throw MockAllInApiException("Requested user not found") + mockFriends.remove(user.first.id to requestUser.first.id) + } + override suspend fun getAllBets(token: String, body: RequestBetFilters): List { getUserFromToken(token) ?: throw MockAllInApiException("Invalid login/password.") return mockBets @@ -399,6 +420,14 @@ class MockAllInApi : AllInApi { private val mockWon by lazy { mutableMapOf>() } private val mockGifts by lazy { mutableMapOf() } + + private val mockFriends by lazy { + mutableSetOf( + "UUID 1" to "UUID 2", + "UUID 2" to "UUID 1", + "UUID 1" to "UUID 3" + ) + } } } diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt index ceb6093..e092fbc 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt @@ -11,7 +11,7 @@ import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.BinaryBet import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail import fr.iut.alldev.allin.data.model.bet.vo.BetDetail import fr.iut.alldev.allin.data.serialization.ZonedDateTimeSerializer @@ -34,7 +34,7 @@ data class ResponseBet( ) { fun toBet(): Bet = when { response.toSet() == setOf(YES_VALUE, NO_VALUE) -> { - YesNoBet( + BinaryBet( id = id ?: "", theme = theme, phrase = sentenceBet, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiFriend.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiFriend.kt new file mode 100644 index 0000000..1b6e3d8 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiFriend.kt @@ -0,0 +1,8 @@ +package fr.iut.alldev.allin.data.api.model + +import androidx.annotation.Keep +import kotlinx.serialization.Serializable + +@Keep +@Serializable +data class RequestFriend(val username: String) \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/di/RepositoryModule.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/di/RepositoryModule.kt index 7fd8a97..04d2980 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/di/RepositoryModule.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/di/RepositoryModule.kt @@ -5,8 +5,10 @@ import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import fr.iut.alldev.allin.data.repository.BetRepository +import fr.iut.alldev.allin.data.repository.FriendRepository import fr.iut.alldev.allin.data.repository.UserRepository import fr.iut.alldev.allin.data.repository.impl.BetRepositoryImpl +import fr.iut.alldev.allin.data.repository.impl.FriendRepositoryImpl import fr.iut.alldev.allin.data.repository.impl.UserRepositoryImpl import javax.inject.Singleton @@ -20,4 +22,8 @@ abstract class RepositoryModule { @Singleton @Binds abstract fun provideBetRepository(betRepositoryImpl: BetRepositoryImpl): BetRepository + + @Singleton + @Binds + abstract fun provideFriendRepository(friendRepositoryImpl: FriendRepositoryImpl): FriendRepository } \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt index b4ea653..e6a0d59 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt @@ -20,7 +20,7 @@ class BetFactory { ): Bet = when (betType) { BetType.BINARY -> { - YesNoBet( + BinaryBet( id = id, theme = theme, creator = creator, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BinaryBet.kt similarity index 96% rename from src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt rename to src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BinaryBet.kt index fc1cf47..db2bcf8 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BinaryBet.kt @@ -5,7 +5,7 @@ import java.time.ZonedDateTime const val YES_VALUE = "Yes" const val NO_VALUE = "No" -data class YesNoBet( +data class BinaryBet( override val id: String, override val creator: String, override val theme: String, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/FriendRepository.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/FriendRepository.kt new file mode 100644 index 0000000..2acad60 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/FriendRepository.kt @@ -0,0 +1,9 @@ +package fr.iut.alldev.allin.data.repository + +import fr.iut.alldev.allin.data.model.User + +abstract class FriendRepository { + abstract suspend fun getFriends(token: String): List + abstract suspend fun add(token: String, username: String) + abstract suspend fun remove(token: String, username: String) +} \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt index ef1f85d..c2d95e3 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt @@ -6,16 +6,16 @@ import kotlinx.coroutines.flow.asStateFlow abstract class UserRepository { - internal val _currentUser by lazy { MutableStateFlow(null) } - val currentUser by lazy { _currentUser.asStateFlow() } + internal val currentUser by lazy { MutableStateFlow(null) } + val currentUserState get() = currentUser.asStateFlow() suspend fun resetCurrentUser() { - _currentUser.emit(null) + currentUser.emit(null) } suspend fun updateCurrentUserCoins(value: Int) { - currentUser.value?.let { user -> - _currentUser.emit( + currentUserState.value?.let { user -> + currentUser.emit( user.copy( coins = value ) @@ -24,9 +24,7 @@ abstract class UserRepository { } abstract suspend fun login(username: String, password: String): String? - abstract suspend fun login(token: String): String? - abstract suspend fun register(username: String, email: String, password: String): String? abstract suspend fun dailyGift(token: String): Int } \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/FriendRepositoryImpl.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/FriendRepositoryImpl.kt new file mode 100644 index 0000000..d9ec122 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/FriendRepositoryImpl.kt @@ -0,0 +1,30 @@ +package fr.iut.alldev.allin.data.repository.impl + +import fr.iut.alldev.allin.data.api.AllInApi +import fr.iut.alldev.allin.data.api.AllInApi.Companion.formatBearerToken +import fr.iut.alldev.allin.data.api.model.RequestFriend +import fr.iut.alldev.allin.data.model.User +import fr.iut.alldev.allin.data.repository.FriendRepository +import javax.inject.Inject + +class FriendRepositoryImpl @Inject constructor( + private val api: AllInApi +) : FriendRepository() { + override suspend fun getFriends(token: String): List { + return api.getFriends(token.formatBearerToken()).map { it.toUser() } + } + + override suspend fun add(token: String, username: String) { + return api.addFriend( + token = token.formatBearerToken(), + request = RequestFriend(username) + ) + } + + override suspend fun remove(token: String, username: String) { + return api.deleteFriend( + token = token.formatBearerToken(), + request = RequestFriend(username) + ) + } +} \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt index 3a4e3ae..ba299e4 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt @@ -18,17 +18,16 @@ class UserRepositoryImpl @Inject constructor( password = password ) ) - _currentUser.emit(response.toUser()) + currentUser.emit(response.toUser()) return response.token } override suspend fun login(token: String): String? { val response = api.login(token = token.formatBearerToken()) - _currentUser.emit(response.toUser()) + currentUser.emit(response.toUser()) return response.token } - override suspend fun register(username: String, email: String, password: String): String? { val response = api.register( RequestUser( @@ -37,7 +36,7 @@ class UserRepositoryImpl @Inject constructor( password = password ) ) - _currentUser.emit(response.toUser()) + currentUser.emit(response.toUser()) return response.token } diff --git a/src/gradle/libs.versions.toml b/src/gradle/libs.versions.toml index 30fa123..4a15afe 100644 --- a/src/gradle/libs.versions.toml +++ b/src/gradle/libs.versions.toml @@ -15,7 +15,7 @@ androidxSecurity = "1.1.0-alpha06" composeBom = "2024.05.00" composeCompiler = "1.5.5" composePreview = "1.6.5" -composeNavigation = "2.7.6" +composeNavigation = "2.7.7" hilt = "2.48" hiltNavigation = "1.1.0"