Add home screen
This commit is contained in:
parent
a9dc65d0b6
commit
b6e4d282b7
7 changed files with 173 additions and 21 deletions
|
|
@ -95,6 +95,7 @@ dependencies {
|
|||
implementation "androidx.room:room-ktx:$androidx_room_version"
|
||||
|
||||
implementation "io.coil-kt:coil:$coil_version"
|
||||
implementation "io.coil-kt:coil-compose:$coil_version"
|
||||
|
||||
implementation project(":core")
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package org.fnives.test.showcase.ui.compose.screen
|
|||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -12,6 +11,9 @@ import androidx.navigation.compose.rememberNavController
|
|||
import kotlinx.coroutines.delay
|
||||
import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase
|
||||
import org.fnives.test.showcase.ui.compose.screen.auth.AuthScreen
|
||||
import org.fnives.test.showcase.ui.compose.screen.auth.rememberAuthScreenState
|
||||
import org.fnives.test.showcase.ui.compose.screen.home.HomeScreen
|
||||
import org.fnives.test.showcase.ui.compose.screen.home.rememberHomeScreenState
|
||||
import org.fnives.test.showcase.ui.compose.screen.splash.SplashScreen
|
||||
import org.koin.androidx.compose.get
|
||||
|
||||
|
|
@ -25,9 +27,23 @@ fun AppNavigation() {
|
|||
navController.navigate(if (isUserLogeInUseCase.invoke()) "Home" else "Auth")
|
||||
}
|
||||
|
||||
NavHost(navController, startDestination = "Splash", modifier = Modifier.background(MaterialTheme.colors.surface)) {
|
||||
NavHost(
|
||||
navController,
|
||||
startDestination = "Splash",
|
||||
modifier = Modifier.background(MaterialTheme.colors.surface)
|
||||
) {
|
||||
composable("Splash") { SplashScreen() }
|
||||
composable("Auth") { AuthScreen() }
|
||||
composable("Home") { Text("Home") }
|
||||
composable("Auth") {
|
||||
val authState = rememberAuthScreenState()
|
||||
AuthScreen(authState)
|
||||
if (authState.navigateToHome?.consume() != null) {
|
||||
navController.navigate("Home")
|
||||
}
|
||||
}
|
||||
composable("Home") {
|
||||
HomeScreen(rememberHomeScreenState {
|
||||
navController.navigate("Auth")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ import org.fnives.test.showcase.R
|
|||
|
||||
@Composable
|
||||
fun AuthScreen(
|
||||
authScreenState: AuthScreenState = rememberAuthScreen()
|
||||
authScreenState: AuthScreenState = rememberAuthScreenState()
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import org.fnives.test.showcase.ui.shared.Event
|
|||
import org.koin.androidx.compose.get
|
||||
|
||||
@Composable
|
||||
fun rememberAuthScreen(
|
||||
fun rememberAuthScreenState(
|
||||
stateScope: CoroutineScope = rememberCoroutineScope(),
|
||||
loginUseCase: LoginUseCase = get(),
|
||||
): AuthScreenState {
|
||||
|
|
@ -64,8 +64,7 @@ class AuthScreenState(
|
|||
when (loginStatus) {
|
||||
LoginStatus.SUCCESS -> navigateToHome = Event(Unit)
|
||||
LoginStatus.INVALID_CREDENTIALS -> error = Event(ErrorType.INVALID_CREDENTIALS)
|
||||
LoginStatus.INVALID_USERNAME -> error = Event(ErrorType.UNSUPPORTED_USERNAME).also { println("asdasdasd: ${it.hashCode()}")
|
||||
}
|
||||
LoginStatus.INVALID_USERNAME -> error = Event(ErrorType.UNSUPPORTED_USERNAME)
|
||||
LoginStatus.INVALID_PASSWORD -> error = Event(ErrorType.UNSUPPORTED_PASSWORD)
|
||||
}
|
||||
println("asdasdasd: ${error.hashCode()}")
|
||||
|
|
|
|||
|
|
@ -1,39 +1,100 @@
|
|||
package org.fnives.test.showcase.ui.compose.screen.home
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.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.ColorFilter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.rememberImagePainter
|
||||
import com.google.accompanist.swiperefresh.SwipeRefresh
|
||||
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
|
||||
import org.fnives.test.showcase.R
|
||||
import org.fnives.test.showcase.model.content.FavouriteContent
|
||||
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
homeScreenState = rememberHomeScreenState()
|
||||
homeScreenState: HomeScreenState = rememberHomeScreenState()
|
||||
) {
|
||||
Column(Modifier.fillMaxSize()) {
|
||||
Title()
|
||||
SwipeRefresh(state = rememberSwipeRefreshState(isRefreshing = false), onRefresh = { }) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Title(Modifier.weight(1f))
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.logout_24),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colors.primary),
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.clickable { homeScreenState.onLogout() }
|
||||
)
|
||||
}
|
||||
SwipeRefresh(
|
||||
state = rememberSwipeRefreshState(isRefreshing = homeScreenState.loading),
|
||||
onRefresh = {
|
||||
homeScreenState.onRefresh()
|
||||
}) {
|
||||
LazyColumn {
|
||||
|
||||
items(homeScreenState.content) { item ->
|
||||
Item(
|
||||
Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
favouriteContent = item,
|
||||
onFavouriteToggle = { homeScreenState.onFavouriteToggleClicked(item.content.id) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Item(
|
||||
modifier: Modifier = Modifier,
|
||||
favouriteContent: FavouriteContent,
|
||||
onFavouriteToggle: () -> Unit,
|
||||
) {
|
||||
Row(modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||
Image(
|
||||
painter = rememberImagePainter(favouriteContent.content.imageUrl.url),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
.height(120.dp)
|
||||
.aspectRatio(1f)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
)
|
||||
Column(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Text(text = favouriteContent.content.title)
|
||||
Text(text = favouriteContent.content.description)
|
||||
}
|
||||
Image(
|
||||
painter = painterResource(id = if (favouriteContent.isFavourite) R.drawable.favorite_24 else R.drawable.favorite_border_24),
|
||||
contentDescription = null,
|
||||
Modifier.clickable { onFavouriteToggle() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
private fun Title() {
|
||||
private fun Title(modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
stringResource(id = R.string.login_title),
|
||||
modifier = Modifier.padding(16.dp),
|
||||
modifier = modifier.padding(16.dp),
|
||||
style = MaterialTheme.typography.h4
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,116 @@
|
|||
package org.fnives.test.showcase.ui.compose.screen.home
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase
|
||||
import org.fnives.test.showcase.core.content.FetchContentUseCase
|
||||
import org.fnives.test.showcase.core.content.GetAllContentUseCase
|
||||
import org.fnives.test.showcase.core.content.RemoveContentFromFavouritesUseCase
|
||||
import org.fnives.test.showcase.core.login.LogoutUseCase
|
||||
import org.fnives.test.showcase.model.content.ContentId
|
||||
import org.fnives.test.showcase.model.content.FavouriteContent
|
||||
import org.fnives.test.showcase.model.shared.Resource
|
||||
import org.koin.androidx.compose.get
|
||||
|
||||
@Composable
|
||||
fun rememberHomeScreenState(
|
||||
stateScope: CoroutineScope = rememberCoroutineScope(),
|
||||
getAllContentUseCase: GetAllContentUseCase = get(),
|
||||
logoutUseCase: LogoutUseCase = get(),
|
||||
fetchContentUseCase: FetchContentUseCase = get(),
|
||||
addContentToFavouriteUseCase: AddContentToFavouriteUseCase = get(),
|
||||
removeContentFromFavouritesUseCase: RemoveContentFromFavouritesUseCase = get(),
|
||||
onLogout: () -> Unit = {},
|
||||
): HomeScreenState {
|
||||
return remember {
|
||||
HomeScreenState(
|
||||
stateScope,
|
||||
getAllContentUseCase,
|
||||
logoutUseCase,
|
||||
fetchContentUseCase,
|
||||
addContentToFavouriteUseCase,
|
||||
removeContentFromFavouritesUseCase
|
||||
removeContentFromFavouritesUseCase,
|
||||
onLogout,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class HomeScreenState(
|
||||
private val stateScope: CoroutineScope,
|
||||
private val getAllContentUseCase: GetAllContentUseCase,
|
||||
private val logoutUseCase: LogoutUseCase,
|
||||
private val fetchContentUseCase: FetchContentUseCase,
|
||||
private val addContentToFavouriteUseCase: AddContentToFavouriteUseCase,
|
||||
private val removeContentFromFavouritesUseCase: RemoveContentFromFavouritesUseCase
|
||||
private val removeContentFromFavouritesUseCase: RemoveContentFromFavouritesUseCase,
|
||||
private val logoutEvent: () -> Unit,
|
||||
) {
|
||||
|
||||
var loading by mutableStateOf(false)
|
||||
private set
|
||||
var isError by mutableStateOf(false)
|
||||
private set
|
||||
var content by mutableStateOf<List<FavouriteContent>>(emptyList())
|
||||
private set
|
||||
|
||||
init {
|
||||
stateScope.launch {
|
||||
fetch().collect {
|
||||
content = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetch() = getAllContentUseCase.get()
|
||||
.mapNotNull {
|
||||
when (it) {
|
||||
is Resource.Error -> {
|
||||
isError = true
|
||||
loading = false
|
||||
return@mapNotNull emptyList<FavouriteContent>()
|
||||
}
|
||||
is Resource.Loading -> {
|
||||
isError = false
|
||||
loading = true
|
||||
return@mapNotNull null
|
||||
}
|
||||
is Resource.Success -> {
|
||||
isError = false
|
||||
loading = false
|
||||
return@mapNotNull it.data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onLogout() {
|
||||
stateScope.launch {
|
||||
logoutUseCase.invoke()
|
||||
logoutEvent()
|
||||
}
|
||||
}
|
||||
|
||||
fun onRefresh() {
|
||||
if (loading) return
|
||||
loading = true
|
||||
stateScope.launch {
|
||||
fetchContentUseCase.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun onFavouriteToggleClicked(contentId: ContentId) {
|
||||
stateScope.launch {
|
||||
val item = content.firstOrNull { it.content.id == contentId } ?: return@launch
|
||||
if (item.isFavourite) {
|
||||
removeContentFromFavouritesUseCase.invoke(contentId)
|
||||
} else {
|
||||
addContentToFavouriteUseCase.invoke(contentId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ project.ext {
|
|||
coroutines_version = "1.6.0"
|
||||
turbine_version = "0.7.0"
|
||||
koin_version = "3.1.2"
|
||||
coil_version = "1.1.1"
|
||||
coil_version = "1.4.0"
|
||||
retrofit_version = "2.9.0"
|
||||
okhttp_version = "4.9.1"
|
||||
moshi_version = "1.13.0"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue