Login logic
This commit is contained in:
@@ -3,6 +3,7 @@ package com.ericampire.android.androidstudycase
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
@@ -14,10 +15,11 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
@ExperimentalMaterialApi
|
||||
@ExperimentalPagerApi
|
||||
@ExperimentalPermissionsApi
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.ericampire.android.androidstudycase.app
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
@HiltAndroidApp
|
||||
@@ -8,4 +10,15 @@ class App : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun restart(context: Context) {
|
||||
context.packageManager.getLaunchIntentForPackage(context.packageName)?.apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
addCategory(Intent.CATEGORY_HOME)
|
||||
context.startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ericampire.android.androidstudycase.app
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
@@ -11,6 +12,7 @@ import com.ericampire.android.androidstudycase.util.Destination
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@ExperimentalMaterialApi
|
||||
fun NavGraphBuilder.addHomeScreen(navController: NavController) {
|
||||
composable(Destination.Home.route) {
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.ericampire.android.androidstudycase.presentation.custom
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Facebook
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ericampire.android.androidstudycase.R
|
||||
import com.ericampire.android.androidstudycase.presentation.theme.AppColor
|
||||
|
||||
@Composable
|
||||
fun CustomFacebookButton(
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Button(
|
||||
enabled = enabled,
|
||||
colors = ButtonDefaults.buttonColors(backgroundColor = AppColor.BlueFacebook),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(50.dp),
|
||||
onClick = onClick,
|
||||
content = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
content = {
|
||||
Icon(
|
||||
tint = Color.White,
|
||||
imageVector = Icons.Rounded.Facebook,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
color = Color.White,
|
||||
style = MaterialTheme.typography.h5,
|
||||
text = stringResource(R.string.txt_connect_with_facebook)
|
||||
)
|
||||
Icon(
|
||||
tint = Color.Transparent,
|
||||
imageVector = Icons.Rounded.Facebook,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CustomFacebookButtonPreview() {
|
||||
CustomFacebookButton() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.ericampire.android.androidstudycase.presentation.custom
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Facebook
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.ericampire.android.androidstudycase.R
|
||||
|
||||
|
||||
@Composable
|
||||
fun CustomGoogleButton(
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
OutlinedButton(
|
||||
enabled = enabled,
|
||||
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(50.dp),
|
||||
onClick = onClick,
|
||||
content = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
content = {
|
||||
Icon(
|
||||
tint = Color.Unspecified,
|
||||
painter = painterResource(id = R.drawable.ic_google),
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.h5,
|
||||
color = MaterialTheme.colors.surface,
|
||||
text = stringResource(R.string.txt_connect_with_google)
|
||||
)
|
||||
Icon(
|
||||
tint = Color.Transparent,
|
||||
imageVector = Icons.Rounded.Facebook,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CustomGoogleButtonPreview() {
|
||||
CustomGoogleButton {
|
||||
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -140,8 +140,16 @@ fun ExploreScreen(
|
||||
}
|
||||
is Success -> {
|
||||
val animations = it.invoke()
|
||||
HorizontalPager(state = pagerState) {
|
||||
ExploreContent(files = animations)
|
||||
if (animations.isEmpty()) {
|
||||
// Todo: Empty instead of Loading View
|
||||
LoadingAnimation(
|
||||
waveColor = MaterialTheme.colors.primary.copy(alpha = 0.5f),
|
||||
arcColor = MaterialTheme.colors.primaryVariant
|
||||
)
|
||||
} else {
|
||||
HorizontalPager(state = pagerState) {
|
||||
ExploreContent(files = animations)
|
||||
}
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
|
||||
+2
@@ -2,4 +2,6 @@ package com.ericampire.android.androidstudycase.presentation.screen.home.busines
|
||||
|
||||
sealed interface HomeAction {
|
||||
object FetchData : HomeAction
|
||||
object Login : HomeAction
|
||||
object FetchCurrentUser : HomeAction
|
||||
}
|
||||
+30
-9
@@ -3,17 +3,17 @@ package com.ericampire.android.androidstudycase.presentation.screen.home.busines
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import com.ericampire.android.androidstudycase.app.hilt.AssistedViewModelFactory
|
||||
import com.ericampire.android.androidstudycase.app.hilt.hiltMavericksViewModelFactory
|
||||
import com.ericampire.android.androidstudycase.domain.usecase.FindFeaturedAnimatorUseCase
|
||||
import com.ericampire.android.androidstudycase.domain.usecase.FindFeaturedBlogUseCase
|
||||
import com.ericampire.android.androidstudycase.domain.usecase.FindFeaturedLottieFileUseCase
|
||||
import com.ericampire.android.androidstudycase.domain.usecase.FindUsersUseCase
|
||||
import com.ericampire.android.androidstudycase.domain.usecase.*
|
||||
import com.ericampire.android.androidstudycase.util.PreviewData
|
||||
import com.ericampire.android.androidstudycase.util.data
|
||||
import com.ericampire.android.androidstudycase.util.mvi.BaseViewModel
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class HomeViewModel @AssistedInject constructor(
|
||||
@@ -21,7 +21,8 @@ class HomeViewModel @AssistedInject constructor(
|
||||
private val findFeaturedBlogUseCase: FindFeaturedBlogUseCase,
|
||||
private val findFeaturedAnimatorUseCase: FindFeaturedAnimatorUseCase,
|
||||
private val findUsersUseCase: FindUsersUseCase,
|
||||
private val findFeaturedLottieFileUseCase: FindFeaturedLottieFileUseCase
|
||||
private val findFeaturedLottieFileUseCase: FindFeaturedLottieFileUseCase,
|
||||
private val saveUserUseCase: SaveUserUseCase
|
||||
) : BaseViewModel<HomeViewState, HomeAction>(initialState) {
|
||||
|
||||
|
||||
@@ -30,25 +31,45 @@ class HomeViewModel @AssistedInject constructor(
|
||||
pendingAction.collectLatest { action ->
|
||||
when (action) {
|
||||
HomeAction.FetchData -> fetchData()
|
||||
HomeAction.Login -> login()
|
||||
HomeAction.FetchCurrentUser -> fetchCurrentUser()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun login() {
|
||||
viewModelScope.launch {
|
||||
suspend {
|
||||
delay(2000)
|
||||
saveUserUseCase(PreviewData.User.data.first()).data!!
|
||||
}.execute {
|
||||
copy(login = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchCurrentUser() {
|
||||
viewModelScope.launch {
|
||||
findUsersUseCase(Unit).map {
|
||||
it.data?.firstOrNull()
|
||||
}.execute {
|
||||
copy(currentUser = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchData() {
|
||||
val userFlow = findUsersUseCase(Unit)
|
||||
val storiesFlow = findFeaturedBlogUseCase(Unit)
|
||||
val animatorsFlow = findFeaturedAnimatorUseCase(Unit)
|
||||
val animationsFlow = findFeaturedLottieFileUseCase(Unit)
|
||||
|
||||
combine(
|
||||
userFlow,
|
||||
storiesFlow,
|
||||
animationsFlow,
|
||||
animatorsFlow
|
||||
) { user, stories, anim, animators ->
|
||||
) { stories, anim, animators ->
|
||||
HomeContentData(
|
||||
user = user.data?.firstOrNull(),
|
||||
blog = stories.data ?: emptyList(),
|
||||
featuredAnimators = animators.data ?: emptyList(),
|
||||
featuredLottieFile = anim.data ?: emptyList(),
|
||||
|
||||
+3
-2
@@ -9,12 +9,13 @@ import com.ericampire.android.androidstudycase.domain.entity.Lottiefile
|
||||
import com.ericampire.android.androidstudycase.domain.entity.User
|
||||
|
||||
data class HomeViewState(
|
||||
val contentData: Async<HomeContentData> = Uninitialized
|
||||
val contentData: Async<HomeContentData> = Uninitialized,
|
||||
val login: Async<Unit> = Uninitialized,
|
||||
val currentUser: Async<User?> = Uninitialized,
|
||||
) : MavericksState
|
||||
|
||||
data class HomeContentData(
|
||||
val blog: List<Blog> = emptyList(),
|
||||
val featuredAnimators: List<Animator> = emptyList(),
|
||||
val featuredLottieFile: List<Lottiefile> = emptyList(),
|
||||
val user: User? = null,
|
||||
) : MavericksState
|
||||
|
||||
+84
-48
@@ -1,6 +1,7 @@
|
||||
package com.ericampire.android.androidstudycase.presentation.screen.home.ui
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -9,16 +10,16 @@ import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
@@ -29,6 +30,8 @@ import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.compose.collectAsState
|
||||
import com.airbnb.mvrx.compose.mavericksViewModel
|
||||
import com.ericampire.android.androidstudycase.R
|
||||
import com.ericampire.android.androidstudycase.app.App
|
||||
import com.ericampire.android.androidstudycase.domain.entity.User
|
||||
import com.ericampire.android.androidstudycase.presentation.custom.CustomImageView
|
||||
import com.ericampire.android.androidstudycase.presentation.custom.LoadingAnimation
|
||||
import com.ericampire.android.androidstudycase.presentation.custom.TopActionBar
|
||||
@@ -37,9 +40,10 @@ import com.ericampire.android.androidstudycase.presentation.screen.home.business
|
||||
import com.ericampire.android.androidstudycase.presentation.screen.home.business.HomeViewModel
|
||||
import com.ericampire.android.androidstudycase.presentation.screen.home.business.HomeViewState
|
||||
import com.ericampire.android.androidstudycase.presentation.theme.AppColor
|
||||
import com.ericampire.android.androidstudycase.util.Destination
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@ExperimentalMaterialApi
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
@@ -48,56 +52,87 @@ fun HomeScreen(
|
||||
) {
|
||||
|
||||
val state by viewModel.collectAsState(HomeViewState::contentData)
|
||||
val loginState by viewModel.collectAsState(HomeViewState::login)
|
||||
val userState by viewModel.collectAsState(HomeViewState::currentUser)
|
||||
|
||||
val bottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
LaunchedEffect(viewModel) {
|
||||
viewModel.submitAction(HomeAction.FetchData)
|
||||
viewModel.submitAction(HomeAction.FetchCurrentUser)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = AppColor.Black001),
|
||||
content = {
|
||||
TopActionBar()
|
||||
}
|
||||
LaunchedEffect(loginState) {
|
||||
if (loginState is Success) {
|
||||
App.restart(context)
|
||||
}
|
||||
}
|
||||
|
||||
ModalBottomSheetLayout(
|
||||
sheetShape = RoundedCornerShape(topEnd = 24.dp, topStart = 24.dp),
|
||||
sheetState = bottomSheetState,
|
||||
sheetContent = {
|
||||
LoginBottomSheet(
|
||||
onLoginClick = {
|
||||
viewModel.submitAction(HomeAction.Login)
|
||||
},
|
||||
isLoading = loginState is Loading
|
||||
)
|
||||
},
|
||||
content = { contentPadding ->
|
||||
Crossfade(modifier = Modifier.padding(contentPadding), targetState = state) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
content = {
|
||||
when (it) {
|
||||
Uninitialized -> {
|
||||
LoadingAnimation(
|
||||
waveColor = MaterialTheme.colors.primary.copy(alpha = 0.5f),
|
||||
arcColor = MaterialTheme.colors.primaryVariant
|
||||
)
|
||||
}
|
||||
is Loading -> {
|
||||
LoadingAnimation(
|
||||
waveColor = MaterialTheme.colors.primary.copy(alpha = 0.5f),
|
||||
arcColor = MaterialTheme.colors.primaryVariant
|
||||
)
|
||||
}
|
||||
is Success -> {
|
||||
HomeContent(
|
||||
state = it.invoke(),
|
||||
onLoginClick = {
|
||||
navController.navigate(Destination.Login.route)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Fail -> {
|
||||
Timber.e(it.error.localizedMessage)
|
||||
}
|
||||
content = {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = AppColor.Black001),
|
||||
content = {
|
||||
TopActionBar()
|
||||
}
|
||||
)
|
||||
},
|
||||
content = { contentPadding ->
|
||||
Crossfade(modifier = Modifier.padding(contentPadding), targetState = state) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
content = {
|
||||
when (it) {
|
||||
Uninitialized -> {
|
||||
LoadingAnimation(
|
||||
waveColor = MaterialTheme.colors.primary.copy(alpha = 0.5f),
|
||||
arcColor = MaterialTheme.colors.primaryVariant
|
||||
)
|
||||
}
|
||||
is Loading -> {
|
||||
LoadingAnimation(
|
||||
waveColor = MaterialTheme.colors.primary.copy(alpha = 0.5f),
|
||||
arcColor = MaterialTheme.colors.primaryVariant
|
||||
)
|
||||
}
|
||||
is Success -> {
|
||||
HomeContent(
|
||||
state = it.invoke(),
|
||||
currentUser = userState.invoke(),
|
||||
onLoginClick = {
|
||||
coroutineScope.launch {
|
||||
bottomSheetState.animateTo(targetValue = ModalBottomSheetValue.Expanded)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
is Fail -> {
|
||||
Timber.e(it.error.localizedMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -107,6 +142,7 @@ fun HomeScreen(
|
||||
fun HomeContent(
|
||||
modifier: Modifier = Modifier,
|
||||
state: HomeContentData,
|
||||
currentUser: User? = null,
|
||||
onLoginClick: () -> Unit
|
||||
) {
|
||||
LazyColumn(
|
||||
@@ -117,10 +153,10 @@ fun HomeContent(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
content = {
|
||||
item {
|
||||
if (state.user == null) {
|
||||
if (currentUser == null) {
|
||||
UnLoggedUserHeaderView(onLoginClick = onLoginClick)
|
||||
} else {
|
||||
LoggedUserHeaderView(user = state.user)
|
||||
LoggedUserHeaderView(user = currentUser)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ fun LoggedUserHeaderView(
|
||||
content = {
|
||||
Text(
|
||||
maxLines = 1,
|
||||
text = "Monday September 4",
|
||||
text = "Monday 4 September",
|
||||
style = MaterialTheme.typography.button.copy(
|
||||
color = Color.Gray
|
||||
),
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package com.ericampire.android.androidstudycase.presentation.screen.home.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
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 com.airbnb.lottie.compose.*
|
||||
import com.ericampire.android.androidstudycase.R
|
||||
import com.ericampire.android.androidstudycase.presentation.custom.CustomFacebookButton
|
||||
import com.ericampire.android.androidstudycase.presentation.custom.CustomGoogleButton
|
||||
import com.ericampire.android.androidstudycase.presentation.theme.AndroidStudyCaseTheme
|
||||
import com.ericampire.android.androidstudycase.presentation.theme.AppColor
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@Composable
|
||||
fun LoginBottomSheet(
|
||||
modifier: Modifier = Modifier,
|
||||
isLoading: Boolean = false,
|
||||
onLoginClick: () -> Unit,
|
||||
) {
|
||||
|
||||
val composition by rememberLottieComposition(
|
||||
spec = LottieCompositionSpec.RawRes(R.raw.people_communicating)
|
||||
)
|
||||
val progress by animateLottieCompositionAsState(
|
||||
composition = composition,
|
||||
iterations = LottieConstants.IterateForever,
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.background(AppColor.Black001),
|
||||
content = {
|
||||
AnimatedVisibility(isLoading) {
|
||||
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
content = {
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResource(id = R.string.txt_login_title),
|
||||
style = MaterialTheme.typography.h4.copy(
|
||||
color = MaterialTheme.colors.onSurface
|
||||
),
|
||||
)
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResource(id = R.string.txt_login_description),
|
||||
style = MaterialTheme.typography.body1.copy(
|
||||
color = MaterialTheme.colors.onSurface
|
||||
),
|
||||
)
|
||||
LottieAnimation(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(200.dp),
|
||||
composition = composition,
|
||||
progress = progress,
|
||||
)
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResource(id = R.string.txt_get_started),
|
||||
style = MaterialTheme.typography.body1.copy(
|
||||
color = MaterialTheme.colors.onSurface
|
||||
),
|
||||
)
|
||||
|
||||
CustomFacebookButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onLoginClick
|
||||
)
|
||||
|
||||
CustomGoogleButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onLoginClick
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@ExperimentalMaterialApi
|
||||
@Preview()
|
||||
@Composable
|
||||
fun LoginDialogViewPreview() {
|
||||
AndroidStudyCaseTheme(darkTheme = true) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center,
|
||||
content = {
|
||||
LoginBottomSheet(
|
||||
onLoginClick = {}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -44,7 +44,7 @@ fun UnLoggedUserHeaderView(
|
||||
content = {
|
||||
Text(
|
||||
maxLines = 1,
|
||||
text = "Monday September 4",
|
||||
text = "Monday 4 September",
|
||||
style = MaterialTheme.typography.button.copy(
|
||||
color = Color.Gray
|
||||
),
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
package com.ericampire.android.androidstudycase.presentation.screen.main.ui
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -29,7 +30,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
@ExperimentalMaterialApi
|
||||
@ExperimentalPagerApi
|
||||
@ExperimentalPermissionsApi
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@Composable
|
||||
fun MainScreen() {
|
||||
val navController = rememberNavController()
|
||||
|
||||
+2
-1
@@ -12,7 +12,8 @@ object AppColor {
|
||||
val Purple700 = Color(0xFF3700B3)
|
||||
val Teal200 = Color(0xFF03DAC5)
|
||||
val Black001 = Color(0xFF222222)
|
||||
val BlackOverlay = Color(0x4D000000)
|
||||
val BlueFacebook = Color(0xFF3B5998)
|
||||
val BlackOverlay = Color(0x4DFFFFFF)
|
||||
val BlackOverlay001 = Color(0x1A000000)
|
||||
val WhiteTransparent = Color(0x80FFFFFF)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M23.745,12.27C23.745,11.48 23.675,10.73 23.555,10L12.255,10L12.255,14.51L18.725,14.51C18.435,15.99 17.585,17.24 16.325,18.09L16.325,21.09L20.185,21.09C22.445,19 23.745,15.92 23.745,12.27Z"
|
||||
android:fillColor="#4285F4" />
|
||||
<path
|
||||
android:pathData="M12.255,24C15.495,24 18.205,22.92 20.185,21.09L16.325,18.09C15.245,18.81 13.875,19.25 12.255,19.25C9.125,19.25 6.475,17.14 5.525,14.29L1.545,14.29L1.545,17.38C3.515,21.3 7.565,24 12.255,24Z"
|
||||
android:fillColor="#34A853" />
|
||||
<path
|
||||
android:pathData="M5.525,14.29C5.275,13.57 5.145,12.8 5.145,12C5.145,11.2 5.285,10.43 5.525,9.71L5.525,6.62L1.545,6.62C0.725,8.24 0.255,10.06 0.255,12C0.255,13.94 0.725,15.76 1.545,17.38L5.525,14.29Z"
|
||||
android:fillColor="#FBBC05" />
|
||||
<path
|
||||
android:pathData="M12.255,4.75C14.025,4.75 15.605,5.36 16.855,6.55L20.275,3.13C18.205,1.19 15.495,0 12.255,0C7.565,0 3.515,2.7 1.545,6.62L5.525,9.71C6.475,6.86 9.125,4.75 12.255,4.75Z"
|
||||
android:fillColor="#EA4335" />
|
||||
</vector>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,7 @@
|
||||
<string name="txt_featured_animation">Featured Animations</string>
|
||||
<string name="txt_open_setting">Open Settings</string>
|
||||
<string name="txt_request">Request permission</string>
|
||||
<string name="txt_login_title">1000s of lottie animations</string>
|
||||
<string name="txt_login_description">from top creators waiting to be discover, save and share from the palm of your hand</string>
|
||||
<string name="txt_connect_with_facebook">Continue with Facebook</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user