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

ThemeChanging Functionality Added #2723

Open
wants to merge 6 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
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
23 changes: 16 additions & 7 deletions androidApp/src/main/kotlin/org/mifos/mobile/HomeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.mifos.mobile.core.data.utils.NetworkMonitor
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.designsystem.theme.darkScrim
import org.mifos.mobile.core.designsystem.theme.lightScrim
import org.mifos.mobile.core.model.enums.AppTheme
import org.mifos.mobile.navigation.MifosNavGraph.AUTH_GRAPH
import org.mifos.mobile.navigation.MifosNavGraph.PASSCODE_GRAPH
import org.mifos.mobile.navigation.RootNavGraph
Expand All @@ -54,7 +55,6 @@ class HomeActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
var uiState: HomeActivityUiState by mutableStateOf(HomeActivityUiState.Loading)

// Update the uiState
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState
Expand All @@ -76,25 +76,34 @@ class HomeActivity : ComponentActivity() {
val navController = rememberNavController()

val appState = rememberMifosMobileState(networkMonitor = networkMonitor)
val darkTheme= isSystemInDarkTheme()

val navDestination = when (uiState) {
is Success -> if ((uiState as Success).userData.isAuthenticated) {
PASSCODE_GRAPH
} else {
AUTH_GRAPH
}

else -> AUTH_GRAPH
}

DisposableEffect(darkTheme) {
window?.statusBarColor = if (darkTheme) darkScrim.toArgb() else lightScrim.toArgb()
window?.navigationBarColor = if (darkTheme) darkScrim.toArgb() else lightScrim.toArgb()
val isSystemInDarkMode = isSystemInDarkTheme()
DisposableEffect(isSystemInDarkMode) {
window?.statusBarColor = if (isSystemInDarkMode) darkScrim.toArgb() else lightScrim.toArgb()
revanthkumarJ marked this conversation as resolved.
Show resolved Hide resolved
window?.navigationBarColor = if (isSystemInDarkMode) darkScrim.toArgb() else lightScrim.toArgb()
onDispose {}
}

val isDarkMode = when (uiState) {
is Success -> when ((uiState as Success).themeState) {
AppTheme.DARK -> true
AppTheme.LIGHT -> false
AppTheme.SYSTEM -> isSystemInDarkMode
}
else -> isSystemInDarkMode
}

CompositionLocalProvider {
MifosMobileTheme {
MifosMobileTheme(isDarkMode) {
RootNavGraph(
appState = appState,
navHostController = navController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,28 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.mifos.library.passcode.data.PasscodeManager
import org.mifos.mobile.core.data.repository.UserDataRepository
import org.mifos.mobile.core.datastore.PreferencesHelper
import org.mifos.mobile.core.model.UserData
import org.mifos.mobile.core.model.enums.AppTheme
import javax.inject.Inject

@HiltViewModel
class HomeActivityViewModel @Inject constructor(
private val userDataRepository: UserDataRepository,
private val passcodeManager: PasscodeManager,
private val preferencesHelper: PreferencesHelper,
) : ViewModel() {

val uiState: StateFlow<HomeActivityUiState> = userDataRepository.userData.map {
HomeActivityUiState.Success(it)
val uiState: StateFlow<HomeActivityUiState> = combine(
userDataRepository.userData,
preferencesHelper.themeFlow,
) { userData, themeState ->
HomeActivityUiState.Success(userData, themeState)
}.stateIn(
scope = viewModelScope,
initialValue = HomeActivityUiState.Loading,
Expand All @@ -46,5 +52,5 @@ class HomeActivityViewModel @Inject constructor(

sealed interface HomeActivityUiState {
data object Loading : HomeActivityUiState
data class Success(val userData: UserData) : HomeActivityUiState
data class Success(val userData: UserData, val themeState: AppTheme) : HomeActivityUiState
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import androidx.multidex.MultiDexApplication
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.raizlabs.android.dbflow.config.FlowManager
import dagger.hilt.android.HiltAndroidApp
import org.mifos.mobile.core.datastore.PreferencesHelper
import org.mifos.mobile.feature.settings.applySavedTheme

@HiltAndroidApp
class MifosSelfServiceApp : MultiDexApplication() {
Expand All @@ -24,7 +22,6 @@ class MifosSelfServiceApp : MultiDexApplication() {
MultiDex.install(this)
FlowManager.init(this)
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true)
PreferencesHelper(this).applySavedTheme()
}

override fun onTerminate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import android.text.TextUtils
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.callbackFlow
import org.mifos.mobile.core.model.enums.AppTheme
Expand All @@ -29,9 +32,23 @@ import javax.inject.Singleton
*/
@Singleton
class PreferencesHelper @Inject constructor(@ApplicationContext context: Context?) {
private val themeFlowState: MutableStateFlow<AppTheme>
val themeFlow: StateFlow<AppTheme> get() = themeFlowState.asStateFlow()

private val sharedPreferences: SharedPreferences? =
PreferenceManager.getDefaultSharedPreferences(context)

init {
if (!sharedPreferences?.contains(APPLICATION_THEME)!!) {
putInt(APPLICATION_THEME, AppTheme.SYSTEM.ordinal)
}
themeFlowState = MutableStateFlow(
AppTheme.entries.getOrNull(
sharedPreferences.getInt(APPLICATION_THEME, AppTheme.SYSTEM.ordinal),
) ?: AppTheme.SYSTEM,
)
}

fun clear() {
val editor = sharedPreferences?.edit()
// prevent deletion of url and tenant
Expand Down Expand Up @@ -178,6 +195,7 @@ class PreferencesHelper @Inject constructor(@ApplicationContext context: Context
get() = getInt(APPLICATION_THEME, AppTheme.SYSTEM.ordinal) ?: AppTheme.SYSTEM.ordinal
set(value) {
putInt(APPLICATION_THEME, value)
themeFlowState.value = AppTheme.entries[value]
}

var language
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ val LightSurfaceTint = Color(0xFF325CA8)
val DarkSurfaceTint = Color(0xFFAEC6FF)

val lightScrim = Color(0x80FFFFFF)
val darkScrim = Color(0x80000000)
val darkScrim = Color(0x80000000)
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
*/
package org.mifos.mobile.feature.settings

import android.os.Build
import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down Expand Up @@ -70,15 +68,7 @@ internal class SettingsViewModel @Inject constructor(
}

fun updateTheme(theme: AppTheme) {
AppCompatDelegate.setDefaultNightMode(
when (theme) {
AppTheme.DARK -> AppCompatDelegate.MODE_NIGHT_YES
AppTheme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
},
)
preferencesHelper.appTheme = theme.ordinal
preferencesHelper.applyTheme(theme)
}
}

Expand Down Expand Up @@ -124,27 +114,3 @@ internal enum class SettingsCardItem(
subclassOf = R.string.other,
),
}

fun PreferencesHelper.applySavedTheme() {
val applicationTheme = AppTheme.entries.find { it.ordinal == this.appTheme }
AppCompatDelegate.setDefaultNightMode(
when {
applicationTheme == AppTheme.DARK -> AppCompatDelegate.MODE_NIGHT_YES
applicationTheme == AppTheme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
Build.VERSION.SDK_INT > Build.VERSION_CODES.P -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_NO
},
)
}

internal fun PreferencesHelper.applyTheme(applicationTheme: AppTheme) {
this.appTheme = applicationTheme.ordinal
AppCompatDelegate.setDefaultNightMode(
when {
applicationTheme == AppTheme.DARK -> AppCompatDelegate.MODE_NIGHT_YES
applicationTheme == AppTheme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
Build.VERSION.SDK_INT > Build.VERSION_CODES.P -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_NO
},
)
}
Loading