Skip to content

Commit

Permalink
Merge pull request #183 from Devendra34/feature/account_compose
Browse files Browse the repository at this point in the history
Migrate account feature from XML to Jetpack Compose
  • Loading branch information
hieuwu authored Oct 3, 2023
2 parents d539e86 + 492abe8 commit 62588bf
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 248 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ dependencies {
implementation libs.glide
annotationProcessor libs.glide.compiler
implementation libs.lottie
implementation libs.lottie.compose

implementation libs.bundles.retrofit
implementation libs.gson
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,30 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import com.hieuwu.groceriesstore.R
import com.hieuwu.groceriesstore.databinding.FragmentAccountBinding
import com.hieuwu.groceriesstore.presentation.AuthActivity
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch

@AndroidEntryPoint
class AccountFragment : Fragment() {

private lateinit var binding: FragmentAccountBinding
private val viewModel: AccountViewModel by viewModels()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate<FragmentAccountBinding>(
inflater, R.layout.fragment_account, container, false
)

binding.viewModel = viewModel
binding.lifecycleOwner = this
setObserver()
setEventListener()

return binding.root
}

private fun setObserver() {
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
viewModel.user.collect {}
}
): View {

return ComposeView(requireContext()).apply {
setContent {
AccountScreen(
onSignInClick = ::navigateToAuthentication,
onProfileSettingsClick = ::navigateToProfileSettings,
onNotificationSettingsClick = ::navigateToNotificationsSettings,
onOrderHistorySettingsClick = ::navigateToOrderHistory,
)
}
}
}
Expand All @@ -56,27 +38,15 @@ class AccountFragment : Fragment() {
startActivity(intent)
}

private fun setEventListener() {
with(binding) {
profileLayout.setOnClickListener {
findNavController().navigate(R.id.action_accountFragment_to_updateProfileFragment)
}

notificationSettingLayout.setOnClickListener {
findNavController().navigate(R.id.action_accountFragment_to_notificationSettingsFragment)
}

orderHistoryLayout.setOnClickListener {
findNavController().navigate(R.id.action_accountFragment_to_orderHistoryFragment)
}
private fun navigateToProfileSettings() {
findNavController().navigate(R.id.action_accountFragment_to_updateProfileFragment)
}

signoutButton.setOnClickListener {
viewModel?.signOut()
}
private fun navigateToNotificationsSettings() {
findNavController().navigate(R.id.action_accountFragment_to_notificationSettingsFragment)
}

signinButton.setOnClickListener {
navigateToAuthentication()
}
}
private fun navigateToOrderHistory() {
findNavController().navigate(R.id.action_accountFragment_to_orderHistoryFragment)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.hieuwu.groceriesstore.presentation.account

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import com.hieuwu.groceriesstore.R
import com.hieuwu.groceriesstore.domain.models.UserModel
import com.hieuwu.groceriesstore.presentation.account.widgets.AccountContentView
import com.hieuwu.groceriesstore.presentation.account.widgets.AccountHeaderView

@Composable
fun AccountScreen(
modifier: Modifier = Modifier,
viewModel: AccountViewModel = hiltViewModel(),
onSignInClick: (() -> Unit),
onProfileSettingsClick: (() -> Unit),
onNotificationSettingsClick: (() -> Unit),
onOrderHistorySettingsClick: (() -> Unit),
) {
val user = viewModel.user.collectAsState()

AccountScreenView(
modifier = modifier,
user = user.value,
onSignInClick = onSignInClick,
onProfileSettingsClick = onProfileSettingsClick,
onNotificationSettingsClick = onNotificationSettingsClick,
onOrderHistorySettingsClick = onOrderHistorySettingsClick,
onSignOutClick = { viewModel.signOut() },
)
}

@Composable
private fun AccountScreenView(
modifier: Modifier = Modifier,
user: UserModel? = null,
onSignInClick: () -> Unit,
onProfileSettingsClick: () -> Unit,
onNotificationSettingsClick: () -> Unit,
onOrderHistorySettingsClick: () -> Unit,
onSignOutClick: () -> Unit,
) {
Scaffold { contentPadding ->
Column(
modifier = modifier.padding(contentPadding),
verticalArrangement = Arrangement.Top
) {

AccountHeaderView(user = user)
AccountContentView(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.margin_medium)),
user = user,
onSignInClick = onSignInClick,
onProfileSettingsClick = onProfileSettingsClick,
onNotificationSettingsClick = onNotificationSettingsClick,
onOrderHistorySettingsClick = onOrderHistorySettingsClick,
onSignOutClick = onSignOutClick,
)
}
}
}

internal val DemoUser = UserModel(
"0", "J.K. Rowling", "[email protected]",
phone = "+1234567890",
address = "Earth",
isOrderCreatedNotiEnabled = false,
isPromotionNotiEnabled = false,
isDataRefreshedNotiEnabled = false
)

@Preview(showSystemUi = true)
@Composable
private fun SignedInAccountScreen() {
AccountScreenView(
user = DemoUser,
onSignInClick = { /*TODO*/ },
onProfileSettingsClick = { /*TODO*/ },
onNotificationSettingsClick = { /*TODO*/ },
onOrderHistorySettingsClick = { /*TODO*/ },
onSignOutClick = { /*TODO*/ },
)
}

@Preview(showSystemUi = true)
@Composable
private fun SignedOutAccountScreen() {
AccountScreenView(
onSignInClick = { /*TODO*/ },
onProfileSettingsClick = { /*TODO*/ },
onNotificationSettingsClick = { /*TODO*/ },
onOrderHistorySettingsClick = { /*TODO*/ },
onSignOutClick = { /*TODO*/ },
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package com.hieuwu.groceriesstore.presentation.account.widgets

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
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.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.graphics.Color
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import com.hieuwu.groceriesstore.R
import com.hieuwu.groceriesstore.domain.models.UserModel
import com.hieuwu.groceriesstore.presentation.account.DemoUser
import com.hieuwu.groceriesstore.presentation.core.widgets.PrimaryButton
import com.hieuwu.groceriesstore.presentation.core.widgets.SecondaryButton

@Composable
fun AccountContentView(
modifier: Modifier = Modifier,
user: UserModel? = null,
onSignInClick: () -> Unit,
onProfileSettingsClick: () -> Unit,
onNotificationSettingsClick: () -> Unit,
onOrderHistorySettingsClick: () -> Unit,
onSignOutClick: () -> Unit,
) {
if (user != null) {
AccountContentSignedInView(
modifier = modifier,
onProfileSettingsClick = onProfileSettingsClick,
onNotificationSettingsClick = onNotificationSettingsClick,
onOrderHistorySettingsClick = onOrderHistorySettingsClick,
onSignOutClick = onSignOutClick,
)
} else {
AccountContentSignedOutView(
modifier = modifier.padding(vertical = dimensionResource(id = R.dimen.margin_medium)),
onSignInClick = onSignInClick
)
}
}

@Composable
fun AccountContentSignedInView(
modifier: Modifier = Modifier,
onProfileSettingsClick: (() -> Unit),
onNotificationSettingsClick: (() -> Unit),
onOrderHistorySettingsClick: (() -> Unit),
onSignOutClick: (() -> Unit),
) {
val actions = listOf(
R.string.profile_information to onProfileSettingsClick,
R.string.notification_settings to onNotificationSettingsClick,
R.string.order_history_settings to onOrderHistorySettingsClick,
)
for (action in actions) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(top = dimensionResource(id = R.dimen.margin_small))
.clickable(onClick = action.second),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(id = action.first),
fontWeight = FontWeight.Bold,
color = Color(0xFF808080),
maxLines = 1
)
Icon(
modifier = Modifier.size(dimensionResource(id = R.dimen.icon_small)),
painter = painterResource(id = R.drawable.ic_baseline_chevron_right_24),
contentDescription = null,
)
}
}

SecondaryButton(
modifier = modifier
.fillMaxWidth()
.padding(vertical = dimensionResource(id = R.dimen.margin_medium)),
onClick = onSignOutClick
) {
Text(text = stringResource(id = R.string.sign_out))
}
}

@Composable
fun AccountContentSignedOutView(
modifier: Modifier = Modifier,
onSignInClick: (() -> Unit),
) {
PrimaryButton(
modifier = modifier.fillMaxWidth(),
onClick = onSignInClick
) {
Text(text = stringResource(id = R.string.sign_in))
}
}

@Preview(showBackground = true)
@Composable
private fun AccountContentViewSignedInStatePreview() {
Column {
AccountContentView(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.margin_medium)),
user = DemoUser,
onSignInClick = {},
onProfileSettingsClick = {},
onNotificationSettingsClick = {},
onOrderHistorySettingsClick = {},
) {}
}
}

@Preview
@Composable
private fun AccountContentViewSignedOutStatePreview() {
Column {
AccountContentView(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.margin_medium)),
onSignInClick = {},
onProfileSettingsClick = {},
onNotificationSettingsClick = {},
onOrderHistorySettingsClick = {},
) {}
}
}
Loading

0 comments on commit 62588bf

Please sign in to comment.