From b17de9915afcb86feb796ee93e903f9e4f7bd5ae Mon Sep 17 00:00:00 2001 From: Avneet Singh Date: Sun, 4 Feb 2024 20:00:53 +0530 Subject: [PATCH] refactor #2503: migrated home screen to compose --- .../mobile/ui/activities/HomeActivity.kt | 1 + .../org/mifos/mobile/ui/home/HomeCards.kt | 14 + .../org/mifos/mobile/ui/home/HomeContent.kt | 295 +++++++++++++++++ .../ui/{fragments => home}/HomeOldFragment.kt | 312 +++++------------- .../org/mifos/mobile/ui/home/HomeScreen.kt | 76 +++++ .../{viewModels => ui/home}/HomeViewModel.kt | 88 +++-- .../ui/user_profile/UserProfileScreen.kt | 6 +- .../org/mifos/mobile/utils/HomeUiState.kt | 14 +- .../mobile/viewModels/HomeViewModelTest.kt | 1 + .../core/ui/component/MifosHiddenTextRow.kt | 65 ++++ .../mobile/core/ui/component/MifosLinkText.kt | 33 ++ .../ui/component/MifosProgressIndicator.kt | 23 ++ .../core/ui/component/MifosTextUserImage.kt | 45 +++ .../core/ui/component/MifosUserImage.kt | 37 +-- .../org/mifos/mobile/core/ui/theme/Color.kt | 5 +- .../org/mifos/mobile/core/ui/theme/Theme.kt | 19 +- 16 files changed, 735 insertions(+), 299 deletions(-) create mode 100644 app/src/main/java/org/mifos/mobile/ui/home/HomeCards.kt create mode 100644 app/src/main/java/org/mifos/mobile/ui/home/HomeContent.kt rename app/src/main/java/org/mifos/mobile/ui/{fragments => home}/HomeOldFragment.kt (50%) create mode 100644 app/src/main/java/org/mifos/mobile/ui/home/HomeScreen.kt rename app/src/main/java/org/mifos/mobile/{viewModels => ui/home}/HomeViewModel.kt (51%) create mode 100644 ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt create mode 100644 ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt create mode 100644 ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt create mode 100644 ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt diff --git a/app/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt b/app/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt index f8bed8dd8..0783ea881 100644 --- a/app/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt +++ b/app/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt @@ -37,6 +37,7 @@ import org.mifos.mobile.ui.enums.ChargeType import org.mifos.mobile.ui.fragments.* import org.mifos.mobile.ui.getThemeAttributeColor import org.mifos.mobile.ui.help.HelpActivity +import org.mifos.mobile.ui.home.HomeOldFragment import org.mifos.mobile.ui.login.LoginActivity import org.mifos.mobile.utils.Constants import org.mifos.mobile.utils.TextDrawable diff --git a/app/src/main/java/org/mifos/mobile/ui/home/HomeCards.kt b/app/src/main/java/org/mifos/mobile/ui/home/HomeCards.kt new file mode 100644 index 000000000..fbd996fec --- /dev/null +++ b/app/src/main/java/org/mifos/mobile/ui/home/HomeCards.kt @@ -0,0 +1,14 @@ +package org.mifos.mobile.ui.home + +import org.mifos.mobile.R +sealed class HomeCardItem( + val titleId: Int, + val drawableResId: Int +) { + data object AccountCard : HomeCardItem(R.string.accounts, R.drawable.ic_account_balance_black_24dp) + data object TransferCard : HomeCardItem(R.string.transfer, R.drawable.ic_compare_arrows_black_24dp) + data object ChargesCard : HomeCardItem(R.string.charges, R.drawable.ic_account_balance_wallet_black_24dp) + data object LoanCard : HomeCardItem(R.string.apply_for_loan, R.drawable.ic_loan) + data object BeneficiariesCard : HomeCardItem(R.string.beneficiaries, R.drawable.ic_beneficiaries_48px) + data object SurveyCard : HomeCardItem(R.string.survey, R.drawable.ic_surveys_48px) +} diff --git a/app/src/main/java/org/mifos/mobile/ui/home/HomeContent.kt b/app/src/main/java/org/mifos/mobile/ui/home/HomeContent.kt new file mode 100644 index 000000000..4e6dd0af0 --- /dev/null +++ b/app/src/main/java/org/mifos/mobile/ui/home/HomeContent.kt @@ -0,0 +1,295 @@ +package org.mifos.mobile.ui.home + +import android.graphics.Bitmap +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +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 org.mifos.mobile.R +import org.mifos.mobile.core.ui.component.MifosHiddenTextRow +import org.mifos.mobile.core.ui.component.MifosLinkText +import org.mifos.mobile.core.ui.component.MifosUserImage +import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.utils.CurrencyUtil + +@Composable +fun HomeContent( + username: String, + totalLoanAmount: Double, + totalSavingsAmount: Double, + userBitmap: Bitmap?, + homeCards: List, + userProfile: () -> Unit, + totalSavings: () -> Unit, + totalLoan: () -> Unit, + callHelpline: (String) -> Unit, + mailHelpline: (String) -> Unit, + homeCardClicked: (HomeCardItem) -> Unit, +) { + val scrollState = rememberScrollState() + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + .verticalScroll(scrollState) + ) { + UserDetailsRow( + userBitmap = userBitmap, + username = username, + userProfile = userProfile + ) + + Spacer(modifier = Modifier.height(8.dp)) + + AccountOverviewCard( + totalLoanAmount = totalLoanAmount, + totalSavingsAmount = totalSavingsAmount, + totalLoan = totalLoan, + totalSavings = totalSavings + ) + + Spacer(modifier = Modifier.height(8.dp)) + + HomeCards(homeCardClicked = homeCardClicked, homeCards = homeCards) + + ContactUsRow(callHelpline = callHelpline, mailHelpline = mailHelpline) + } +} + +@OptIn(ExperimentalLayoutApi::class) +@Composable +private fun HomeCards( + homeCardClicked: (HomeCardItem) -> Unit, + homeCards: List +) { + FlowRow( + modifier = Modifier.fillMaxWidth(), + maxItemsInEachRow = 3, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + homeCards.forEach { card -> + HomeCard( + modifier = Modifier + .weight(1f) + .padding(bottom = 8.dp), + titleId = card.titleId, + drawableResId = card.drawableResId, + onClick = { homeCardClicked(card) } + ) + } + } +} + +@Composable +fun UserDetailsRow( + userBitmap: Bitmap?, + username: String, + userProfile: () -> Unit +) { + val interactionSource = remember { MutableInteractionSource() } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + + MifosUserImage( + modifier = Modifier + .size(84.dp) + .clickable( + indication = null, + interactionSource = interactionSource, + ) { userProfile.invoke() }, + bitmap = userBitmap, + username = username + ) + + Text( + text = stringResource( + R.string.hello_client, + username + ), + style = MaterialTheme.typography.headlineSmall, + color = if (isSystemInDarkTheme()) Color.White else Color.Black, + modifier = Modifier + .padding(horizontal = 20.dp) + .fillMaxWidth(1f) + ) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun HomeCard( + modifier: Modifier, + titleId: Int, + drawableResId: Int, + onClick: () -> Unit +) { + Card( + modifier = modifier, + onClick = { onClick.invoke() } + ) { + Column( + modifier = Modifier + .padding(8.dp) + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + painter = painterResource(id = drawableResId), + contentDescription = null, + modifier = Modifier.size(56.dp), + tint = MaterialTheme.colorScheme.primary + ) + Text( + text = stringResource(id = titleId), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyMedium, + color = if (isSystemInDarkTheme()) Color.White else Color.Black + ) + } + } +} + +@Composable +private fun AccountOverviewCard( + totalLoanAmount: Double, + totalSavingsAmount: Double, + totalSavings: () -> Unit, + totalLoan: () -> Unit +) { + val context = LocalContext.current + + Row { + Card( + modifier = Modifier + .fillMaxWidth(), + colors = CardDefaults.cardColors() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp) + ) { + Text( + text = stringResource(id = R.string.accounts_overview), + style = MaterialTheme.typography.bodyMedium, + color = if (isSystemInDarkTheme()) Color.White else Color.Black + ) + + Divider(modifier = Modifier.padding(top = 8.dp, bottom = 4.dp)) + + MifosHiddenTextRow( + title = stringResource(id = R.string.total_saving), + hiddenText = CurrencyUtil.formatCurrency(context, totalSavingsAmount), + hiddenColor = colorResource(id = R.color.deposit_green), + hidingText = stringResource(id = R.string.hidden_amount), + visibilityIconId = R.drawable.ic_visibility_24px, + visibilityOffIconId = R.drawable.ic_visibility_off_24px, + onClick = totalSavings + ) + + Spacer(modifier = Modifier.height(8.dp)) + + MifosHiddenTextRow( + title = stringResource(id = R.string.total_loan), + hiddenText = CurrencyUtil.formatCurrency(context, totalLoanAmount), + hiddenColor = colorResource(id = R.color.red), + hidingText = stringResource(id = R.string.hidden_amount), + visibilityIconId = R.drawable.ic_visibility_24px, + visibilityOffIconId = R.drawable.ic_visibility_off_24px, + onClick = totalLoan + ) + } + } + } +} + +@Composable +private fun ContactUsRow( + callHelpline: (String) -> Unit, + mailHelpline: (String) -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = stringResource(id = R.string.need_help), + modifier = Modifier.weight(1f), + color = if (isSystemInDarkTheme()) Color.White else Color.Black, + style = MaterialTheme.typography.bodyMedium + ) + + Column { + MifosLinkText( + text = stringResource(id = R.string.help_line_number), + modifier = Modifier.align(Alignment.End), + onClick = callHelpline, + isUnderlined = false + ) + + MifosLinkText( + text = stringResource(id = R.string.contact_email), + modifier = Modifier.align(Alignment.End), + onClick = mailHelpline + ) + } + } +} + +@Preview(showSystemUi = true) +@Composable +fun PreviewHomeContent() { + MifosMobileTheme { + HomeContent( + username = "Mifos", + totalLoanAmount = 32.32, + totalSavingsAmount = 34.43, + userBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888), + callHelpline = {}, + mailHelpline = {}, + totalSavings = {}, + totalLoan = {}, + userProfile = {}, + homeCardClicked = {}, + homeCards = listOf() + ) + } +} diff --git a/app/src/main/java/org/mifos/mobile/ui/fragments/HomeOldFragment.kt b/app/src/main/java/org/mifos/mobile/ui/home/HomeOldFragment.kt similarity index 50% rename from app/src/main/java/org/mifos/mobile/ui/fragments/HomeOldFragment.kt rename to app/src/main/java/org/mifos/mobile/ui/home/HomeOldFragment.kt index d1eef0368..2c238c5ce 100644 --- a/app/src/main/java/org/mifos/mobile/ui/fragments/HomeOldFragment.kt +++ b/app/src/main/java/org/mifos/mobile/ui/home/HomeOldFragment.kt @@ -1,35 +1,45 @@ -package org.mifos.mobile.ui.fragments - -import android.animation.LayoutTransition -import android.content.* -import android.graphics.Bitmap -import android.os.Build +package org.mifos.mobile.ui.home + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.content.IntentFilter +import android.net.Uri import android.os.Bundle -import android.os.Parcelable -import android.view.* -import android.widget.ImageButton +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.View +import android.view.ViewGroup import android.widget.TextView +import android.widget.Toast +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import dagger.hilt.android.AndroidEntryPoint import org.mifos.mobile.R import org.mifos.mobile.api.local.PreferencesHelper -import org.mifos.mobile.databinding.FragmentHomeOldBinding -import org.mifos.mobile.models.client.Client +import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.ui.activities.HomeActivity import org.mifos.mobile.ui.activities.LoanApplicationActivity import org.mifos.mobile.ui.activities.NotificationActivity -import org.mifos.mobile.ui.user_profile.UserProfileActivity import org.mifos.mobile.ui.activities.base.BaseActivity import org.mifos.mobile.ui.enums.AccountType import org.mifos.mobile.ui.enums.ChargeType +import org.mifos.mobile.ui.fragments.BeneficiaryListFragment +import org.mifos.mobile.ui.fragments.ClientAccountsFragment +import org.mifos.mobile.ui.fragments.ClientChargeFragment +import org.mifos.mobile.ui.fragments.SavingsMakeTransferFragment +import org.mifos.mobile.ui.fragments.ThirdPartyTransferFragment import org.mifos.mobile.ui.fragments.base.BaseFragment -import org.mifos.mobile.ui.getThemeAttributeColor -import org.mifos.mobile.utils.* -import org.mifos.mobile.viewModels.HomeViewModel +import org.mifos.mobile.ui.user_profile.UserProfileActivity +import org.mifos.mobile.utils.Constants +import org.mifos.mobile.utils.MaterialDialog +import org.mifos.mobile.utils.Toaster import javax.inject.Inject /** @@ -37,20 +47,15 @@ import javax.inject.Inject */ @AndroidEntryPoint class HomeOldFragment : BaseFragment(), OnRefreshListener { - private var _binding: FragmentHomeOldBinding? = null - private val binding get() = _binding!! private val viewModel: HomeViewModel by viewModels() @JvmField @Inject var preferencesHelper: PreferencesHelper? = null - private var totalLoanAmount = 0.0 - private var totalSavingAmount = 0.0 - private var client: Client? = null + private var clientId: Long? = 0 private var toolbarView: View? = null - private var isDetailVisible: Boolean? = false private var isReceiverRegistered = false private var tvNotificationCount: TextView? = null @@ -59,27 +64,40 @@ class HomeOldFragment : BaseFragment(), OnRefreshListener { container: ViewGroup?, savedInstanceState: Bundle?, ): View { - _binding = FragmentHomeOldBinding.inflate(inflater, container, false) - val rootView = binding.root clientId = preferencesHelper?.clientId setHasOptionsMenu(true) - binding.swipeHomeContainer.setColorSchemeResources( - R.color.blue_light, - R.color.green_light, - R.color.orange_light, - R.color.red_light, - ) - binding.swipeHomeContainer.setOnRefreshListener(this) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - binding.llContainer.layoutTransition - ?.enableTransitionType(LayoutTransition.CHANGING) - } - if (savedInstanceState == null) { - loadClientData() - } setToolbarTitle(getString(R.string.home)) showUserInterface() - return rootView + loadClientData() + + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + MifosMobileTheme { + HomeScreen( + homeUiState = viewModel.homeUiState.value, + homeCards = viewModel.getHomeCardItems(), + callHelpline = { callHelpline() }, + mailHelpline = { mailHelpline() }, + totalSavings = { onClickSavings() }, + totalLoan = { onClickLoan() }, + userProfile = { userImageClicked() }, + homeCardClicked = { handleHomeCardClick(it) } + ) + } + } + } + } + + private fun handleHomeCardClick(homeCardItem: HomeCardItem) { + when (homeCardItem) { + is HomeCardItem.AccountCard -> accountsClicked() + is HomeCardItem.BeneficiariesCard -> beneficiaries() + is HomeCardItem.ChargesCard -> chargesClicked() + is HomeCardItem.LoanCard -> applyForLoan() + is HomeCardItem.SurveyCard -> surveys() + is HomeCardItem.TransferCard -> transferClicked() + } } private val notificationReceiver: BroadcastReceiver = object : BroadcastReceiver() { @@ -128,31 +146,14 @@ class HomeOldFragment : BaseFragment(), OnRefreshListener { } } - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putDouble(Constants.TOTAL_LOAN, totalLoanAmount) - outState.putDouble(Constants.TOTAL_SAVINGS, totalSavingAmount) - outState.putParcelable(Constants.USER_DETAILS, client) - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - if (savedInstanceState != null) { - showUserDetails(savedInstanceState.getParcelable(Constants.USER_DETAILS) as? Client) - viewModel.setUserProfile(preferencesHelper?.userProfileImage) - showLoanAccountDetails(savedInstanceState.getDouble(Constants.TOTAL_LOAN)) - showSavingAccountDetails(savedInstanceState.getDouble(Constants.TOTAL_SAVINGS)) - } - } - override fun onRefresh() { loadClientData() } private fun loadClientData() { viewModel.loadClientAccountDetails() - viewModel.userDetails - viewModel.userImage + viewModel.getUserDetails() + viewModel.getUserImage() } fun showUserInterface() { @@ -172,16 +173,6 @@ class HomeOldFragment : BaseFragment(), OnRefreshListener { ) } - /** - * Provides `totalLoanAmount` fetched from server - * - * @param totalLoanAmount Total Loan amount - */ - fun showLoanAccountDetails(totalLoanAmount: Double) { - this.totalLoanAmount = totalLoanAmount - binding.tvLoanTotalAmount.text = CurrencyUtil.formatCurrency(context, totalLoanAmount) - } - /** * Open LOAN tab under ClientAccountsFragment */ @@ -190,16 +181,6 @@ class HomeOldFragment : BaseFragment(), OnRefreshListener { (activity as HomeActivity?)?.setNavigationViewSelectedItem(R.id.item_accounts) } - /** - * Provides `totalSavingAmount` fetched from server - * - * @param totalSavingAmount Total Saving amount - */ - fun showSavingAccountDetails(totalSavingAmount: Double) { - this.totalSavingAmount = totalSavingAmount - binding.tvSavingTotalAmount.text = CurrencyUtil.formatCurrency(context, totalSavingAmount) - } - /** * Open SAVINGS tab under ClientAccountsFragment */ @@ -208,143 +189,35 @@ class HomeOldFragment : BaseFragment(), OnRefreshListener { (activity as HomeActivity?)?.setNavigationViewSelectedItem(R.id.item_accounts) } - /** - * Fetches Client details and display clientName - * - * @param client Details about client - */ - fun showUserDetails(client: Client?) { - this.client = client - binding.tvUserName.text = getString(R.string.hello_client, client?.displayName) - } - - /** - * Provides with Client image fetched from server - * - * @param bitmap Client Image - */ - fun showUserImage(bitmap: Bitmap?) { - activity?.runOnUiThread { - if (bitmap != null) { - binding.ivCircularUserImage.visibility = View.VISIBLE - binding.ivCircularUserImage.setImageBitmap(bitmap) - } else { - val userName = preferencesHelper?.clientName.let { savedName -> - if (savedName.isNullOrBlank()) { - getString(R.string.app_name) - } else { - savedName - } - } - - val drawable = TextDrawable.builder() - .beginConfig() - .toUpperCase() - .endConfig() - .buildRound( - userName.substring(0, 1), - requireContext().getThemeAttributeColor(R.attr.colorPrimary), - ) - binding.ivCircularUserImage.setImageDrawable(drawable) - } - } - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - lifecycleScope.launchWhenStarted { - viewModel.homeUiState.collect { - when (it) { - is HomeUiState.Loading -> showProgress() - is HomeUiState.UserImage -> { - hideProgress() - showUserImage(it.image) - } - is HomeUiState.ClientAccountDetails -> { - hideProgress() - showLoanAccountDetails(it.loanAccounts) - showSavingAccountDetails(it.savingsAccounts) - } - is HomeUiState.Error -> { - hideProgress() - showError(getString(it.errorMessage)) - } - is HomeUiState.UserDetails -> { - hideProgress() - showUserDetails(it.client) - } - is HomeUiState.UnreadNotificationsCount -> { - hideProgress() - showNotificationCount(it.count) - } - } + viewModel.notificationsCount.collect { count -> + showNotificationCount(count) } } + } - toggleVisibilityButton( - binding.btnSavingTotalAmountVisibility, - binding.tvSavingTotalAmount, - binding.tvSavingTotalAmountHidden, - ) - toggleVisibilityButton( - binding.btnLoanAmountVisibility, - binding.tvLoanTotalAmount, - binding.tvLoanTotalAmountHidden, - ) - - binding.llTotalLoan.setOnClickListener { - onClickLoan() - } - - binding.llTotalSavings.setOnClickListener { - onClickSavings() - } - - binding.ivCircularUserImage.setOnClickListener { - userImageClicked() - } - - binding.llAccounts.setOnClickListener { - accountsClicked() - } - - binding.llTransfer.setOnClickListener { - transferClicked() - } - - binding.llCharges.setOnClickListener { - chargesClicked() - } - - binding.llApplyForLoan.setOnClickListener { - applyForLoan() - } - - binding.llBeneficiaries.setOnClickListener { - beneficiaries() - } - - binding.llSurveys.setOnClickListener { - surveys() - } + private fun callHelpline() { + val intent = Intent(Intent.ACTION_DIAL) + intent.data = Uri.parse("tel:" + getString(R.string.help_line_number)) + startActivity(intent) } - private fun toggleVisibilityButton( - button: ImageButton, - visibleView: View, - hiddenView: View, - ) { - button.setOnClickListener { - if (visibleView.visibility == View.VISIBLE) { - visibleView.visibility = View.GONE - hiddenView.visibility = View.VISIBLE - button.setImageResource(R.drawable.ic_visibility_24px) - } else { - visibleView.visibility = View.VISIBLE - hiddenView.visibility = View.GONE - button.setImageResource(R.drawable.ic_visibility_off_24px) - } + private fun mailHelpline() { + val intent = Intent(Intent.ACTION_SENDTO).apply { + data = Uri.parse("mailto:") + putExtra(Intent.EXTRA_EMAIL, arrayOf(getString(R.string.contact_email))) + putExtra(Intent.EXTRA_SUBJECT, getString(R.string.user_query)) + } + try { + startActivity(intent) + } catch (e: Exception) { + Toast.makeText( + requireContext(), + getString(R.string.no_app_to_support_action), + Toast.LENGTH_SHORT, + ).show() } } @@ -445,30 +318,7 @@ class HomeOldFragment : BaseFragment(), OnRefreshListener { if (checkedItem == R.id.item_about_us || checkedItem == R.id.item_help || checkedItem == R.id.item_settings) { return } - Toaster.show(binding.root, errorMessage) - } - - /** - * Shows [SwipeRefreshLayout] - */ - fun showProgress() { - binding.swipeHomeContainer.isRefreshing = true - } - - /** - * Hides [SwipeRefreshLayout] - */ - fun hideProgress() { - binding.swipeHomeContainer.isRefreshing = false - } - - override fun onDestroyView() { - super.onDestroyView() - if (binding.swipeHomeContainer.isRefreshing) { - binding.swipeHomeContainer.isRefreshing = false - binding.swipeHomeContainer.removeAllViews() - } - _binding = null + Toaster.show(view, errorMessage) } companion object { diff --git a/app/src/main/java/org/mifos/mobile/ui/home/HomeScreen.kt b/app/src/main/java/org/mifos/mobile/ui/home/HomeScreen.kt new file mode 100644 index 000000000..f1327ce80 --- /dev/null +++ b/app/src/main/java/org/mifos/mobile/ui/home/HomeScreen.kt @@ -0,0 +1,76 @@ +package org.mifos.mobile.ui.home + +import android.graphics.Bitmap +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import org.mifos.mobile.R +import org.mifos.mobile.core.ui.component.EmptyDataView +import org.mifos.mobile.core.ui.component.MifosProgressIndicator +import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.utils.HomeState +import org.mifos.mobile.utils.HomeUiState + + +@Composable +fun HomeScreen( + homeUiState: HomeUiState, + userProfile: () -> Unit, + totalSavings: () -> Unit, + totalLoan: () -> Unit, + callHelpline: (String) -> Unit, + mailHelpline: (String) -> Unit, + homeCardClicked: (HomeCardItem) -> Unit, + homeCards: List +) { + when (homeUiState) { + is HomeUiState.Success -> { + HomeContent( + username = homeUiState.homeState.username ?: "", + totalLoanAmount = homeUiState.homeState.loanAmount, + totalSavingsAmount = homeUiState.homeState.savingsAmount, + userBitmap = homeUiState.homeState.image, + homeCards = homeCards, + userProfile = userProfile, + totalSavings = totalSavings, + totalLoan = totalLoan, + callHelpline = callHelpline, + mailHelpline = mailHelpline, + homeCardClicked = homeCardClicked + ) + } + + is HomeUiState.Loading -> { + MifosProgressIndicator(modifier = Modifier.fillMaxSize()) + } + + is HomeUiState.Error -> { + EmptyDataView(icon = R.drawable.ic_error_black_24dp, error = homeUiState.errorMessage) + } + } + +} + +@Preview(showSystemUi = true) +@Composable +fun HomeScreenPreview() { + val homeState = HomeState( + username = "", + savingsAmount = 34.43, + loanAmount = 34.45, + image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888), + ) + MifosMobileTheme { + HomeScreen( + homeUiState = HomeUiState.Success(homeState), + callHelpline = {}, + mailHelpline = {}, + totalSavings = {}, + totalLoan = {}, + userProfile = {}, + homeCardClicked = {}, + homeCards = listOf() + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mifos/mobile/viewModels/HomeViewModel.kt b/app/src/main/java/org/mifos/mobile/ui/home/HomeViewModel.kt similarity index 51% rename from app/src/main/java/org/mifos/mobile/viewModels/HomeViewModel.kt rename to app/src/main/java/org/mifos/mobile/ui/home/HomeViewModel.kt index 07125e4be..4b71633da 100644 --- a/app/src/main/java/org/mifos/mobile/viewModels/HomeViewModel.kt +++ b/app/src/main/java/org/mifos/mobile/ui/home/HomeViewModel.kt @@ -1,11 +1,14 @@ -package org.mifos.mobile.viewModels +package org.mifos.mobile.ui.home import android.util.Base64 +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch import org.mifos.mobile.R @@ -13,6 +16,7 @@ import org.mifos.mobile.api.local.PreferencesHelper import org.mifos.mobile.models.accounts.loan.LoanAccount import org.mifos.mobile.models.accounts.savings.SavingAccount import org.mifos.mobile.repositories.HomeRepository +import org.mifos.mobile.utils.HomeState import org.mifos.mobile.utils.HomeUiState import org.mifos.mobile.utils.ImageUtil import javax.inject.Inject @@ -24,69 +28,72 @@ class HomeViewModel @Inject constructor(private val homeRepositoryImp: HomeRepos @Inject lateinit var preferencesHelper: PreferencesHelper - private val _homeUiState = MutableStateFlow(HomeUiState.Loading) - val homeUiState: StateFlow = _homeUiState + private val _homeUiState = mutableStateOf(HomeUiState.Loading) + val homeUiState: State get() = _homeUiState + + private val _notificationsCount = MutableStateFlow(0) + val notificationsCount: StateFlow get() = _notificationsCount fun loadClientAccountDetails() { viewModelScope.launch { - _homeUiState.value = HomeUiState.Loading homeRepositoryImp.clientAccounts().catch { _homeUiState.value = HomeUiState.Error(R.string.no_internet_connection) }.collect { clientAccounts -> - _homeUiState.value = HomeUiState.ClientAccountDetails( - getLoanAccountDetails(clientAccounts.loanAccounts), - getSavingAccountDetails(clientAccounts.savingsAccounts) + var currentState = (_homeUiState.value as? HomeUiState.Success)?.homeState ?: HomeState() + currentState = currentState.copy( + loanAmount = getLoanAccountDetails(clientAccounts.loanAccounts), + savingsAmount = getSavingAccountDetails(clientAccounts.savingsAccounts) ) - + _homeUiState.value = HomeUiState.Success(currentState) } } } - - val userDetails: Unit - get() { - viewModelScope.launch { - homeRepositoryImp.currentClient().catch { - _homeUiState.value = HomeUiState.Error(R.string.error_fetching_client) - }.collect { client -> - preferencesHelper.officeName = client.officeName - _homeUiState.value = HomeUiState.UserDetails(client) - } + fun getUserDetails() { + viewModelScope.launch { + homeRepositoryImp.currentClient().catch { + _homeUiState.value = HomeUiState.Error(R.string.error_fetching_client) + }.collect { client -> + preferencesHelper.officeName = client.officeName + var currentState = (_homeUiState.value as? HomeUiState.Success)?.homeState ?: HomeState() + currentState = currentState.copy(username = client.displayName) + _homeUiState.value = HomeUiState.Success(currentState) } } + } - val userImage: Unit - get() { - viewModelScope.launch { - setUserProfile(preferencesHelper.userProfileImage) - homeRepositoryImp.clientImage().catch { - _homeUiState.value = HomeUiState.UserImage(null) - }.collect { - val encodedString = it.string() - val pureBase64Encoded = - encodedString.substring(encodedString.indexOf(',') + 1) - preferencesHelper.userProfileImage = pureBase64Encoded - setUserProfile(pureBase64Encoded) - } + fun getUserImage() { + viewModelScope.launch { + setUserProfile(preferencesHelper.userProfileImage) + homeRepositoryImp.clientImage().catch {}.collect { + val encodedString = it.string() + val pureBase64Encoded = + encodedString.substring(encodedString.indexOf(',') + 1) + preferencesHelper.userProfileImage = pureBase64Encoded + setUserProfile(pureBase64Encoded) } } + } + - fun setUserProfile(image: String?) { + private fun setUserProfile(image: String?) { if (image == null) { return } val decodedBytes = Base64.decode(image, Base64.DEFAULT) val decodedBitmap = ImageUtil.instance?.compressImage(decodedBytes) - _homeUiState.value = HomeUiState.UserImage(decodedBitmap) + var currentState = (_homeUiState.value as? HomeUiState.Success)?.homeState ?: HomeState() + currentState = currentState.copy(image = decodedBitmap) + _homeUiState.value = HomeUiState.Success(currentState) } val unreadNotificationsCount: Unit get() { viewModelScope.launch { homeRepositoryImp.unreadNotificationsCount().catch { - _homeUiState.value = HomeUiState.UnreadNotificationsCount(0) + _notificationsCount.value = 0 }.collect { integer -> - _homeUiState.value = HomeUiState.UnreadNotificationsCount(integer) + _notificationsCount.value = integer } } } @@ -121,4 +128,15 @@ class HomeViewModel @Inject constructor(private val homeRepositoryImp: HomeRepos } return totalAmount } + + fun getHomeCardItems(): List { + return listOf( + HomeCardItem.AccountCard, + HomeCardItem.TransferCard, + HomeCardItem.ChargesCard, + HomeCardItem.LoanCard, + HomeCardItem.BeneficiariesCard, + HomeCardItem.SurveyCard + ) + } } \ No newline at end of file diff --git a/app/src/main/java/org/mifos/mobile/ui/user_profile/UserProfileScreen.kt b/app/src/main/java/org/mifos/mobile/ui/user_profile/UserProfileScreen.kt index ad31f0ba3..56f9cd909 100644 --- a/app/src/main/java/org/mifos/mobile/ui/user_profile/UserProfileScreen.kt +++ b/app/src/main/java/org/mifos/mobile/ui/user_profile/UserProfileScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Divider @@ -58,7 +59,10 @@ fun UserProfileScreen( .padding(top = 100.dp, bottom = 20.dp), horizontalArrangement = Arrangement.Center ) { - MifosUserImage(isDarkTheme = isSystemInDarkTheme(), bitmap = bitmap) + MifosUserImage( + bitmap = bitmap, + modifier = Modifier.size(100.dp) + ) } Divider(color = Color(0xFF8E9099)) userDetails.userName?.let { UserProfileField(label = R.string.username, value = it) } diff --git a/app/src/main/java/org/mifos/mobile/utils/HomeUiState.kt b/app/src/main/java/org/mifos/mobile/utils/HomeUiState.kt index 80f6c4687..a22ecedea 100644 --- a/app/src/main/java/org/mifos/mobile/utils/HomeUiState.kt +++ b/app/src/main/java/org/mifos/mobile/utils/HomeUiState.kt @@ -6,8 +6,12 @@ import org.mifos.mobile.models.client.Client sealed class HomeUiState { object Loading : HomeUiState() data class Error(val errorMessage: Int) : HomeUiState() - data class ClientAccountDetails(val loanAccounts: Double, val savingsAccounts: Double) : HomeUiState() - data class UserDetails(val client: Client) : HomeUiState() - data class UserImage(val image: Bitmap?) : HomeUiState() - data class UnreadNotificationsCount(val count: Int) : HomeUiState() -} \ No newline at end of file + data class Success(val homeState: HomeState): HomeUiState() +} + +data class HomeState( + val username: String? = "", + val image: Bitmap? = null, + val loanAmount: Double = 0.0, + val savingsAmount: Double = 0.0 +) \ No newline at end of file diff --git a/app/src/test/java/org/mifos/mobile/viewModels/HomeViewModelTest.kt b/app/src/test/java/org/mifos/mobile/viewModels/HomeViewModelTest.kt index 121002645..b2978e6f3 100644 --- a/app/src/test/java/org/mifos/mobile/viewModels/HomeViewModelTest.kt +++ b/app/src/test/java/org/mifos/mobile/viewModels/HomeViewModelTest.kt @@ -18,6 +18,7 @@ import org.mifos.mobile.models.accounts.savings.SavingAccount import org.mifos.mobile.models.client.Client import org.mifos.mobile.models.client.ClientAccounts import org.mifos.mobile.repositories.HomeRepositoryImp +import org.mifos.mobile.ui.home.HomeViewModel import org.mifos.mobile.util.RxSchedulersOverrideRule import org.mifos.mobile.utils.HomeUiState import org.mockito.Mock diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt new file mode 100644 index 000000000..54c7523fa --- /dev/null +++ b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt @@ -0,0 +1,65 @@ +package org.mifos.mobile.core.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp + +@Composable +fun MifosHiddenTextRow( + modifier: Modifier = Modifier, + title: String, + hiddenText: String, + hiddenColor: Color, + hidingText: String, + visibilityIconId: Int, + visibilityOffIconId: Int, + onClick: () -> Unit +) { + var isHidden by remember { mutableStateOf(true) } + Row(modifier.clickable { onClick.invoke() }, verticalAlignment = Alignment.CenterVertically) { + Text( + text = title, + style = MaterialTheme.typography.labelMedium, + modifier = Modifier + .alpha(0.7f) + .weight(1f) + ) + Text( + text = if (isHidden) hidingText + else hiddenText, + style = MaterialTheme.typography.bodyLarge, + fontWeight = FontWeight.Bold, + color = hiddenColor + ) + IconButton( + onClick = { isHidden = !isHidden }, + modifier = Modifier + .padding(start = 6.dp) + .size(24.dp) + ) { + Icon( + painter = if (isHidden) painterResource(id = visibilityIconId) + else painterResource(id = visibilityOffIconId), + contentDescription = "Show or hide total amount", + tint = MaterialTheme.colorScheme.primary, + ) + } + } +} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt new file mode 100644 index 000000000..1a9ef763f --- /dev/null +++ b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt @@ -0,0 +1,33 @@ +package org.mifos.mobile.core.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.ui.theme.Blue700 + +@Composable +fun MifosLinkText( + modifier: Modifier = Modifier, + text: String, + onClick: (String) -> Unit, + isUnderlined: Boolean = true +) { + Text( + text = text, + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.primary, + textDecoration = if(isUnderlined) TextDecoration.Underline else null + ), + modifier = modifier + .padding(vertical = 2.dp) + .clickable { + onClick(text) + }, + ) +} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt new file mode 100644 index 000000000..447d40dca --- /dev/null +++ b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt @@ -0,0 +1,23 @@ +package org.mifos.mobile.core.ui.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview + +@Preview(showSystemUi = true) +@Composable +fun MifosProgressIndicator( + modifier: Modifier = Modifier +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator() + } +} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt new file mode 100644 index 000000000..f707b6324 --- /dev/null +++ b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt @@ -0,0 +1,45 @@ +package org.mifos.mobile.core.ui.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity +import kotlin.math.min + +@Composable +fun MifosTextUserImage(modifier: Modifier = Modifier, text: String) { + var boxSize by remember { mutableStateOf(Size.Zero) } + Box( + modifier = modifier + .clip(CircleShape) + .background(color = MaterialTheme.colorScheme.primary) + .onGloballyPositioned { coordinates -> + boxSize = Size( + coordinates.size.width.toFloat(), + coordinates.size.height.toFloat() + ) + }, + contentAlignment = Alignment.Center + ) { + Text( + text = text, + color = MaterialTheme.colorScheme.onPrimary, + fontSize = with(LocalDensity.current) { + (min(boxSize.width, boxSize.height) / 2).toSp() + } + ) + } +} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt index e249affaa..72bca7019 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt +++ b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt @@ -3,15 +3,13 @@ package org.mifos.mobile.core.ui.component import android.graphics.Bitmap import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.unit.dp /** * @author pratyush @@ -20,22 +18,23 @@ import androidx.compose.ui.unit.dp @Composable fun MifosUserImage( - isDarkTheme: Boolean, - bitmap: Bitmap + bitmap: Bitmap?, + modifier: Modifier = Modifier, + username: String? = null ) { - val backgroundColor = if (isDarkTheme) { - Color(0xFF9bb1e3) + if (bitmap == null) { + MifosTextUserImage( + modifier = modifier, + text = username?.firstOrNull()?.toString() ?: "M" + ) } else { - Color(0xFF325ca8) + Image( + modifier = modifier + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primary), + bitmap = bitmap.asImageBitmap(), + contentDescription = "Profile Image", + contentScale = ContentScale.Crop, + ) } - Image( - modifier = Modifier - .size(100.dp) - .clip(CircleShape) - .background(backgroundColor), - bitmap = bitmap.asImageBitmap(), - contentDescription = "Profile Image", - contentScale = ContentScale.Crop, - ) - -} \ No newline at end of file +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt b/ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt index 59520f9a3..c56cff0fa 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt +++ b/ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt @@ -10,4 +10,7 @@ val Black2 = Color(0xFF000000) val BackgroundLight = Color(0xFFFEFBFF) val BackgroundDark = Color(0xFF1B1B1F) -val RedErrorDark = Color(0xFFB00020) \ No newline at end of file +val RedErrorDark = Color(0xFFB00020) + +val LightPrimary = Color(0xFF325ca8) +val DarkPrimary = Color(0xFF9bb1e3) \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt b/ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt index 924beda10..aca22cc38 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt +++ b/ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt @@ -4,22 +4,27 @@ import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext private val LightThemeColors = lightColorScheme( - primary = Blue600, - onPrimary = Black2, + primary = LightPrimary, + onPrimary = Color.White, error = RedErrorDark, background = BackgroundLight, onSurface = Black2, + outlineVariant = Color.Gray ) private val DarkThemeColors = darkColorScheme( - primary = Blue700, + primary = DarkPrimary, + onPrimary = Color.White, secondary = Black1, error = RedErrorDark, background = BackgroundDark, surface = Black1, + outlineVariant = Color.White ) @Composable @@ -29,10 +34,10 @@ fun MifosMobileTheme( ) { val context = LocalContext.current val colors = when { - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { - if (useDarkTheme) dynamicDarkColorScheme(context) - else dynamicLightColorScheme(context) - } +// (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { +// if (useDarkTheme) dynamicDarkColorScheme(context) +// else dynamicLightColorScheme(context) +// } useDarkTheme -> DarkThemeColors else -> LightThemeColors }