Refactoring
This commit is contained in:
@@ -3,11 +3,9 @@ package com.ericampire.android.androidstudycase
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.material.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.main.ui.MainScreen
|
import com.ericampire.android.androidstudycase.presentation.screen.main.ui.MainScreen
|
||||||
import com.ericampire.android.androidstudycase.presentation.theme.AndroidStudyCaseTheme
|
import com.ericampire.android.androidstudycase.presentation.theme.AndroidStudyCaseTheme
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
@@ -15,6 +13,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
@ExperimentalMaterialApi
|
||||||
@ExperimentalPagerApi
|
@ExperimentalPagerApi
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.ericampire.android.androidstudycase.app
|
package com.ericampire.android.androidstudycase.app
|
||||||
|
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.NavGraphBuilder
|
import androidx.navigation.NavGraphBuilder
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.explore.ui.ExploreScreen
|
import com.ericampire.android.androidstudycase.presentation.screen.explore.ui.ExploreScreen
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.home.business.HomeViewModel
|
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.home.ui.HomeScreen
|
import com.ericampire.android.androidstudycase.presentation.screen.home.ui.HomeScreen
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.preview.ui.PreviewScreen
|
import com.ericampire.android.androidstudycase.presentation.screen.preview.ui.PreviewScreen
|
||||||
import com.ericampire.android.androidstudycase.util.Destination
|
import com.ericampire.android.androidstudycase.util.Destination
|
||||||
@@ -20,6 +20,7 @@ fun NavGraphBuilder.addHomeScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalMaterialApi
|
||||||
@ExperimentalPagerApi
|
@ExperimentalPagerApi
|
||||||
fun NavGraphBuilder.addExploreScreen(navController: NavController) {
|
fun NavGraphBuilder.addExploreScreen(navController: NavController) {
|
||||||
composable(Destination.Explore.route) {
|
composable(Destination.Explore.route) {
|
||||||
|
|||||||
-3
@@ -2,7 +2,4 @@ package com.ericampire.android.androidstudycase.presentation.screen.explore.busi
|
|||||||
|
|
||||||
sealed interface ExploreEffect {
|
sealed interface ExploreEffect {
|
||||||
data class ShowErrorMessage(val message: String) : ExploreEffect
|
data class ShowErrorMessage(val message: String) : ExploreEffect
|
||||||
object Loading : ExploreEffect
|
|
||||||
object Success : ExploreEffect
|
|
||||||
object Idle : ExploreEffect
|
|
||||||
}
|
}
|
||||||
+11
-29
@@ -32,48 +32,30 @@ class ExploreViewModel @Inject constructor(
|
|||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
pendingAction.collectLatest { action ->
|
pendingAction.collectLatest { action ->
|
||||||
when(action) {
|
when (action) {
|
||||||
ExploreAction.FindFeaturedFile -> findFeaturedFile()
|
ExploreAction.FindFeaturedFile -> findFeaturedLottieFileUseCase(Unit).fetchData()
|
||||||
ExploreAction.FindPopularFile -> findPopularFile()
|
ExploreAction.FindPopularFile -> findPopularLottieFileUseCase(Unit).fetchData()
|
||||||
ExploreAction.FindRecentFile -> findRecentFile()
|
ExploreAction.FindRecentFile -> findRecentLottieFileUseCase(Unit).fetchData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Flow<Result<List<Lottiefile>>>.fetchData() = intent {
|
private fun Flow<Result<List<Lottiefile>>>.fetchData() = intent(registerIdling = false) {
|
||||||
collect { result ->
|
collect { result ->
|
||||||
when(result) {
|
when (result) {
|
||||||
is Result.Error -> {
|
is Result.Error -> {
|
||||||
val errorMessage = result.exception.localizedMessage ?: "Unknown Error"
|
val errorMessage = result.exception.localizedMessage ?: "Unknown Error"
|
||||||
|
reduce { state.copy(isLoading = false) }
|
||||||
postSideEffect(ExploreEffect.ShowErrorMessage(errorMessage))
|
postSideEffect(ExploreEffect.ShowErrorMessage(errorMessage))
|
||||||
}
|
}
|
||||||
Result.Loading -> {
|
Result.Loading -> reduce {
|
||||||
postSideEffect(ExploreEffect.Loading)
|
state.copy(isLoading = true)
|
||||||
}
|
}
|
||||||
is Result.Success -> {
|
is Result.Success -> reduce {
|
||||||
postSideEffect(ExploreEffect.Success)
|
state.copy(files = result.data, isLoading = false)
|
||||||
reduce { state.copy(files = result.data) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findRecentFile() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
findRecentLottieFileUseCase(Unit).fetchData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findPopularFile() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
findPopularLottieFileUseCase(Unit).fetchData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findFeaturedFile() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
findFeaturedLottieFileUseCase(Unit).fetchData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+2
-1
@@ -3,5 +3,6 @@ package com.ericampire.android.androidstudycase.presentation.screen.explore.busi
|
|||||||
import com.ericampire.android.androidstudycase.domain.entity.Lottiefile
|
import com.ericampire.android.androidstudycase.domain.entity.Lottiefile
|
||||||
|
|
||||||
data class ExploreViewState(
|
data class ExploreViewState(
|
||||||
val files: List<Lottiefile> = emptyList()
|
val files: List<Lottiefile> = emptyList(),
|
||||||
|
val isLoading: Boolean = false
|
||||||
)
|
)
|
||||||
|
|||||||
+52
-28
@@ -1,8 +1,10 @@
|
|||||||
package com.ericampire.android.androidstudycase.presentation.screen.explore.ui
|
package com.ericampire.android.androidstudycase.presentation.screen.explore.ui
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
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.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
@@ -10,27 +12,27 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringArrayResource
|
import androidx.compose.ui.res.stringArrayResource
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.ericampire.android.androidstudycase.R
|
import com.ericampire.android.androidstudycase.R
|
||||||
|
import com.ericampire.android.androidstudycase.domain.entity.Lottiefile
|
||||||
|
import com.ericampire.android.androidstudycase.presentation.custom.LoadingView
|
||||||
import com.ericampire.android.androidstudycase.presentation.custom.TopActionBar
|
import com.ericampire.android.androidstudycase.presentation.custom.TopActionBar
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.explore.business.ExploreAction
|
import com.ericampire.android.androidstudycase.presentation.screen.explore.business.ExploreAction
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.explore.business.ExploreEffect
|
import com.ericampire.android.androidstudycase.presentation.screen.explore.business.ExploreEffect
|
||||||
import com.ericampire.android.androidstudycase.presentation.screen.explore.business.ExploreViewModel
|
import com.ericampire.android.androidstudycase.presentation.screen.explore.business.ExploreViewModel
|
||||||
import com.ericampire.android.androidstudycase.presentation.theme.AppColor
|
import com.ericampire.android.androidstudycase.presentation.theme.AppColor
|
||||||
import com.google.accompanist.insets.navigationBarsPadding
|
|
||||||
import com.google.accompanist.insets.statusBarsPadding
|
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
||||||
import com.google.accompanist.pager.rememberPagerState
|
import com.google.accompanist.pager.rememberPagerState
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
|
@ExperimentalMaterialApi
|
||||||
@ExperimentalPagerApi
|
@ExperimentalPagerApi
|
||||||
@Composable
|
@Composable
|
||||||
fun ExploreScreen(
|
fun ExploreScreen(
|
||||||
@@ -38,12 +40,22 @@ fun ExploreScreen(
|
|||||||
viewModel: ExploreViewModel
|
viewModel: ExploreViewModel
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val effects by viewModel.container.sideEffectFlow.collectAsState(ExploreEffect.Idle)
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val state by viewModel.container.stateFlow.collectAsState()
|
val state by viewModel.container.stateFlow.collectAsState()
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
val tabItems = stringArrayResource(id = R.array.explore_item)
|
val tabItems = stringArrayResource(id = R.array.explore_item)
|
||||||
val pagerState = rememberPagerState(pageCount = tabItems.size)
|
val pagerState = rememberPagerState(pageCount = tabItems.size)
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
LaunchedEffect(viewModel) {
|
||||||
|
viewModel.container.sideEffectFlow.collect {
|
||||||
|
when (it) {
|
||||||
|
is ExploreEffect.ShowErrorMessage -> {
|
||||||
|
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(viewModel) {
|
LaunchedEffect(viewModel) {
|
||||||
viewModel.submitAction(ExploreAction.FindRecentFile)
|
viewModel.submitAction(ExploreAction.FindRecentFile)
|
||||||
@@ -62,7 +74,9 @@ fun ExploreScreen(
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth().background(color = AppColor.Black001),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(color = AppColor.Black001),
|
||||||
content = {
|
content = {
|
||||||
TopActionBar()
|
TopActionBar()
|
||||||
TabRow(
|
TabRow(
|
||||||
@@ -108,27 +122,37 @@ fun ExploreScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
content = { contentPadding ->
|
content = { contentPadding ->
|
||||||
Crossfade(modifier = Modifier.padding(contentPadding), targetState = effects) {
|
Box(
|
||||||
Box(
|
modifier = Modifier
|
||||||
modifier = Modifier.fillMaxSize(),
|
.padding(contentPadding)
|
||||||
contentAlignment = Alignment.Center,
|
.fillMaxSize(),
|
||||||
content = {
|
contentAlignment = Alignment.Center,
|
||||||
when(it) {
|
content = {
|
||||||
ExploreEffect.Idle -> {
|
if (state.isLoading) {
|
||||||
Timber.e("Idel")
|
LoadingView()
|
||||||
}
|
|
||||||
ExploreEffect.Loading -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
is ExploreEffect.ShowErrorMessage -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
ExploreEffect.Success -> {
|
|
||||||
val data = state.files
|
|
||||||
Timber.e(data.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (state.files.isNotEmpty()) {
|
||||||
|
ExploreContent(files = state.files)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExperimentalMaterialApi
|
||||||
|
@Composable
|
||||||
|
fun ExploreContent(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
files: List<Lottiefile>
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = modifier.fillMaxSize(),
|
||||||
|
content = {
|
||||||
|
items(items = files, key = { it.toString() }) { lottieFile ->
|
||||||
|
LottieFileItemView(
|
||||||
|
lottiefile = lottieFile,
|
||||||
|
onClick = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -25,6 +25,7 @@ import com.google.accompanist.insets.navigationBarsPadding
|
|||||||
import com.google.accompanist.insets.statusBarsPadding
|
import com.google.accompanist.insets.statusBarsPadding
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
|
|
||||||
|
@ExperimentalMaterialApi
|
||||||
@ExperimentalPagerApi
|
@ExperimentalPagerApi
|
||||||
@Composable
|
@Composable
|
||||||
fun MainScreen() {
|
fun MainScreen() {
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Android Study Case</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
+7
-11
@@ -1,14 +1,10 @@
|
|||||||
package com.ericampire.android.androidstudycase.domain.entity
|
package com.ericampire.android.androidstudycase.domain.entity
|
||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.Entity
|
||||||
import com.ericampire.android.androidstudycase.domain.util.DateSerializer
|
import androidx.room.Ignore
|
||||||
import com.ericampire.android.androidstudycase.util.room.DateConverter
|
import androidx.room.PrimaryKey
|
||||||
import kotlinx.serialization.Contextual
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import java.util.*
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.JsonNames
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class LottieFilesApiResponse(
|
data class LottieFilesApiResponse(
|
||||||
@@ -37,13 +33,13 @@ data class LottieFilesPage(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@Entity
|
@Entity
|
||||||
class Lottiefile(
|
data class Lottiefile(
|
||||||
@PrimaryKey var id: Long? = null,
|
@PrimaryKey var id: Long? = null,
|
||||||
var bgColor: String = "",
|
var bgColor: String = "",
|
||||||
var lottieUrl: String = "",
|
var lottieUrl: String = "",
|
||||||
var gifUrl: String = "",
|
var gifUrl: String? = "",
|
||||||
var videoUrl: String = "",
|
var videoUrl: String? = "",
|
||||||
var imageUrl: String = "",
|
var imageUrl: String? = "",
|
||||||
var name: String = "",
|
var name: String = "",
|
||||||
// @TypeConverters(DateConverter::class)
|
// @TypeConverters(DateConverter::class)
|
||||||
// @Serializable(with = DateSerializer::class)
|
// @Serializable(with = DateSerializer::class)
|
||||||
|
|||||||
Reference in New Issue
Block a user