Friends Screen + fix string resources format
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
4612f88c69
commit
e29c5d7152
@ -0,0 +1,48 @@
|
||||
package fr.iut.alldev.allin.ui.friends
|
||||
|
||||
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.hilt.navigation.compose.hiltViewModel
|
||||
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
|
||||
|
||||
@Composable
|
||||
fun FriendsScreen(
|
||||
viewModel: FriendsScreenViewModel = hiltViewModel()
|
||||
) {
|
||||
var search by remember { viewModel.search }
|
||||
val state by remember { viewModel.state }
|
||||
|
||||
when (val s = state) {
|
||||
is FriendsScreenViewModel.State.Loaded -> {
|
||||
var deleted by remember { mutableStateOf(emptyList<User>()) }
|
||||
val filteredFriends = remember(search) {
|
||||
s.friends.filter {
|
||||
it.username.contains(search, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
FriendsScreenContent(
|
||||
friends = filteredFriends,
|
||||
deleted = deleted,
|
||||
search = search,
|
||||
setSearch = { search = it },
|
||||
onToggleDeleteFriend = {
|
||||
deleted = if (deleted.contains(it)) {
|
||||
deleted - it
|
||||
} else {
|
||||
deleted + it
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
FriendsScreenViewModel.State.Loading -> {
|
||||
AllInLoading(visible = true)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package fr.iut.alldev.allin.ui.friends
|
||||
|
||||
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.model.User
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class FriendsScreenViewModel @Inject constructor(
|
||||
) : ViewModel() {
|
||||
|
||||
val search by lazy { mutableStateOf("") }
|
||||
val state by lazy { mutableStateOf<State>(State.Loading) }
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
state.value = State.Loaded(mockFriends)
|
||||
}
|
||||
}
|
||||
|
||||
sealed class State {
|
||||
data object Loading: State()
|
||||
|
||||
data class Loaded(val friends: List<User>): 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
|
||||
)
|
||||
)
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package fr.iut.alldev.allin.ui.friends.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
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.ext.asPaddingValues
|
||||
import fr.iut.alldev.allin.theme.AllInColorToken
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.AllInTextField
|
||||
|
||||
@Composable
|
||||
fun FriendsScreenContent(
|
||||
friends: List<User>,
|
||||
deleted: List<User>,
|
||||
search: String,
|
||||
onToggleDeleteFriend: (User) -> Unit,
|
||||
setSearch: (String) -> Unit,
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = WindowInsets.navigationBars.asPaddingValues(start = 24.dp, end = 24.dp, top = 18.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(11.dp),
|
||||
) {
|
||||
item {
|
||||
Text(
|
||||
text = stringResource(id = R.string.friends_title),
|
||||
style = AllInTheme.typography.h1,
|
||||
color = AllInColorToken.allInGrey,
|
||||
fontSize = 24.sp,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
stickyHeader {
|
||||
AllInTextField(
|
||||
value = search,
|
||||
onValueChange = setSearch,
|
||||
leadingIcon = rememberVectorPainter(image = Icons.Default.Search),
|
||||
modifier = Modifier
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
0.5f to AllInTheme.colors.mainSurface,
|
||||
1f to Color.Transparent
|
||||
)
|
||||
)
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
items(friends) {
|
||||
FriendsScreenLine(
|
||||
username = it.username,
|
||||
isFriend = it !in deleted,
|
||||
toggleIsFriend = { onToggleDeleteFriend(it) }
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun FriendsScreenContentPreview() {
|
||||
AllInTheme {
|
||||
FriendsScreenContent(
|
||||
friends = emptyList(),
|
||||
deleted = emptyList(),
|
||||
search = "",
|
||||
setSearch = {},
|
||||
onToggleDeleteFriend = {}
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package fr.iut.alldev.allin.ui.friends.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
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.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.R
|
||||
import fr.iut.alldev.allin.theme.AllInColorToken
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.AllInButton
|
||||
import fr.iut.alldev.allin.ui.core.ProfilePicture
|
||||
|
||||
@Composable
|
||||
fun FriendsScreenLine(
|
||||
username: String,
|
||||
isFriend: Boolean,
|
||||
toggleIsFriend: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
ProfilePicture(
|
||||
size = 50.dp
|
||||
)
|
||||
|
||||
Text(
|
||||
text = username,
|
||||
color = AllInTheme.colors.onBackground2,
|
||||
style = AllInTheme.typography.sm2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
|
||||
AllInButton(
|
||||
color = if (isFriend) {
|
||||
AllInTheme.colors.background
|
||||
} else {
|
||||
AllInColorToken.allInPurple
|
||||
},
|
||||
text = if (isFriend) {
|
||||
stringResource(id = R.string.generic_delete)
|
||||
} else {
|
||||
stringResource(id = R.string.generic_add)
|
||||
},
|
||||
textColor = if (isFriend) {
|
||||
AllInTheme.colors.onBackground
|
||||
} else {
|
||||
AllInColorToken.white
|
||||
},
|
||||
isSmall = true,
|
||||
textStyle = AllInTheme.typography.sm2,
|
||||
onClick = toggleIsFriend,
|
||||
modifier = Modifier.weight(.5f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun FriendsScreenLinePreview() {
|
||||
AllInTheme {
|
||||
FriendsScreenLine(
|
||||
username = "Random",
|
||||
isFriend = false,
|
||||
toggleIsFriend = { }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun FriendsScreenLineIsFriendPreview() {
|
||||
AllInTheme {
|
||||
FriendsScreenLine(
|
||||
username = "Random",
|
||||
isFriend = true,
|
||||
toggleIsFriend = { }
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in new issue