Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate account feature from XML to Jetpack Compose #183

Merged
merged 2 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,137 @@
package com.hieuwu.groceriesstore.presentation.account.widgets

import androidx.compose.foundation.Image
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.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)),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(id = action.first),
fontWeight = FontWeight.Bold,
color = Color(0xFF808080),
maxLines = 1
)
Image(
modifier = Modifier.size(dimensionResource(id = R.dimen.icon_small)),
painter = painterResource(id = R.drawable.ic_baseline_chevron_right_24),
contentDescription = null,
)
Devendra34 marked this conversation as resolved.
Show resolved Hide resolved
}
}

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
Loading