From 94f5ae6bdecc09b3a06c0b0cb9c9ad9d13743e41 Mon Sep 17 00:00:00 2001 From: aritra Date: Thu, 16 May 2024 16:08:24 +0530 Subject: [PATCH] Impl. `Theme State` & `In-app ss blocking` --- .../geekymusketeers/uncrack/MainActivity.kt | 15 ++++- .../uncrack/components/AccountOption.kt | 61 ------------------- .../uncrack/components/UCSwitchCard.kt | 56 +++++++++++++++++ .../uncrack/navigation/Navigation.kt | 13 ++-- .../presentation/account/AccountItems.kt | 27 -------- .../{account => }/profile/ProfileScreen.kt | 2 +- .../{account => settings}/SettingsScreen.kt | 52 ++++++++++------ .../settings/SettingsViewModel.kt | 24 ++++++++ .../uncrack/sharedViewModel/ThemeViewModel.kt | 6 -- .../geekymusketeers/uncrack/ui/theme/Theme.kt | 3 +- 10 files changed, 138 insertions(+), 121 deletions(-) delete mode 100644 app/src/main/java/com/geekymusketeers/uncrack/components/AccountOption.kt create mode 100644 app/src/main/java/com/geekymusketeers/uncrack/components/UCSwitchCard.kt delete mode 100644 app/src/main/java/com/geekymusketeers/uncrack/presentation/account/AccountItems.kt rename app/src/main/java/com/geekymusketeers/uncrack/presentation/{account => }/profile/ProfileScreen.kt (98%) rename app/src/main/java/com/geekymusketeers/uncrack/presentation/{account => settings}/SettingsScreen.kt (83%) create mode 100644 app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsViewModel.kt diff --git a/app/src/main/java/com/geekymusketeers/uncrack/MainActivity.kt b/app/src/main/java/com/geekymusketeers/uncrack/MainActivity.kt index 98445154..9f42863d 100644 --- a/app/src/main/java/com/geekymusketeers/uncrack/MainActivity.kt +++ b/app/src/main/java/com/geekymusketeers/uncrack/MainActivity.kt @@ -6,19 +6,32 @@ import androidx.activity.ComponentActivity import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels import androidx.annotation.RequiresApi import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import com.geekymusketeers.uncrack.navigation.Navigation +import com.geekymusketeers.uncrack.presentation.settings.SettingsViewModel import com.geekymusketeers.uncrack.ui.theme.UnCrackTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class MainActivity : ComponentActivity() { + private val settingsViewModel: SettingsViewModel by viewModels() + @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { + settingsViewModel.isScreenshotEnabled.observe(this) { isEnabled -> + if (isEnabled) { + window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_SECURE) + } else { + window.setFlags(android.view.WindowManager.LayoutParams.FLAG_SECURE, + android.view.WindowManager.LayoutParams.FLAG_SECURE) + } + } + enableEdgeToEdge( statusBarStyle = SystemBarStyle.light( Color.Transparent.toArgb(), Color.Transparent.toArgb() @@ -31,7 +44,7 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setContent { UnCrackTheme { - Navigation() + Navigation(this) } } } diff --git a/app/src/main/java/com/geekymusketeers/uncrack/components/AccountOption.kt b/app/src/main/java/com/geekymusketeers/uncrack/components/AccountOption.kt deleted file mode 100644 index 698fa90f..00000000 --- a/app/src/main/java/com/geekymusketeers/uncrack/components/AccountOption.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.geekymusketeers.uncrack.components - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -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.platform.LocalContext -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage -import coil.request.ImageRequest -import com.geekymusketeers.uncrack.presentation.account.AccountItems -import com.geekymusketeers.uncrack.ui.theme.OnSurfaceLight -import com.geekymusketeers.uncrack.ui.theme.normal16 - -@Composable -fun AccountOption( - accountItem: AccountItems, - modifier: Modifier = Modifier, - onClick: (AccountItems) -> Unit -) { - - val context = LocalContext.current - - Row( - modifier = modifier - .fillMaxWidth() - .clickable { onClick(accountItem) } - .padding(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.Start), - verticalAlignment = Alignment.CenterVertically, - ) { - - AsyncImage( - model = ImageRequest.Builder(context) - .data(accountItem.icon) - .size(coil.size.Size.ORIGINAL) - .build(), contentDescription = null, - modifier = Modifier.size(24.dp) - ) - - Text( - text = accountItem.itemsName, - style = normal16.copy(color = OnSurfaceLight) - ) - } -} - -@Preview(showBackground = true) -@Composable -private fun SettingsItemPreview() { - AccountOption(AccountItems.BIOMETRIC) { - // Do something - } -} \ No newline at end of file diff --git a/app/src/main/java/com/geekymusketeers/uncrack/components/UCSwitchCard.kt b/app/src/main/java/com/geekymusketeers/uncrack/components/UCSwitchCard.kt new file mode 100644 index 00000000..4771b941 --- /dev/null +++ b/app/src/main/java/com/geekymusketeers/uncrack/components/UCSwitchCard.kt @@ -0,0 +1,56 @@ +package com.geekymusketeers.uncrack.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +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.Switch +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.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import com.geekymusketeers.uncrack.R +import com.geekymusketeers.uncrack.ui.theme.OnSurfaceLight +import com.geekymusketeers.uncrack.ui.theme.medium18 + +@Composable +fun UCSwitchCard( + itemName: String, + isChecked: Boolean, + modifier: Modifier = Modifier, + textColor: Color = OnSurfaceLight, + onChecked: (Boolean) -> Unit +) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.Start), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = itemName, + style = medium18.copy(textColor) + ) + + Spacer(modifier = Modifier.weight(1f)) + + Switch( + modifier = Modifier.semantics { + contentDescription = "Theme switcher" + }, + checked = isChecked, + onCheckedChange = onChecked + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/geekymusketeers/uncrack/navigation/Navigation.kt b/app/src/main/java/com/geekymusketeers/uncrack/navigation/Navigation.kt index 591e86fc..d913fefc 100644 --- a/app/src/main/java/com/geekymusketeers/uncrack/navigation/Navigation.kt +++ b/app/src/main/java/com/geekymusketeers/uncrack/navigation/Navigation.kt @@ -1,6 +1,7 @@ package com.geekymusketeers.uncrack.navigation import android.annotation.SuppressLint +import android.app.Activity import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.material3.Icon @@ -27,14 +28,14 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.geekymusketeers.uncrack.R -import com.geekymusketeers.uncrack.presentation.account.SettingsScreen +import com.geekymusketeers.uncrack.presentation.settings.SettingsScreen import com.geekymusketeers.uncrack.presentation.tools.PasswordGenerator import com.geekymusketeers.uncrack.presentation.tools.viewModel.PasswordGeneratorViewModel import com.geekymusketeers.uncrack.presentation.browse.category.CategoryScreen import com.geekymusketeers.uncrack.presentation.browse.BrowseScreen import com.geekymusketeers.uncrack.sharedViewModel.UserViewModel import com.geekymusketeers.uncrack.presentation.masterKey.UpdateMasterKey -import com.geekymusketeers.uncrack.presentation.account.profile.ProfileScreen +import com.geekymusketeers.uncrack.presentation.profile.ProfileScreen import com.geekymusketeers.uncrack.presentation.tools.PasswordHealthScreen import com.geekymusketeers.uncrack.presentation.tools.ToolsScreen import com.geekymusketeers.uncrack.presentation.tools.viewModel.ShieldViewModel @@ -54,6 +55,7 @@ import com.geekymusketeers.uncrack.ui.theme.OnSurfaceVariantLight import com.geekymusketeers.uncrack.ui.theme.PrimaryDark import com.geekymusketeers.uncrack.util.BackPressHandler import com.geekymusketeers.uncrack.presentation.masterKey.KeyViewModel +import com.geekymusketeers.uncrack.presentation.settings.SettingsViewModel import com.geekymusketeers.uncrack.presentation.vault.viewmodel.VaultViewModel import com.geekymusketeers.uncrack.presentation.vault.viewmodel.ViewPasswordViewModel import kotlinx.collections.immutable.ImmutableList @@ -63,6 +65,7 @@ import kotlinx.collections.immutable.persistentListOf @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun Navigation( + activity: Activity, modifier: Modifier = Modifier, masterKeyViewModel: KeyViewModel = hiltViewModel(), passwordGeneratorViewModel: PasswordGeneratorViewModel = hiltViewModel(), @@ -71,7 +74,8 @@ fun Navigation( vaultViewModel: VaultViewModel = hiltViewModel(), addEditViewModel: AddEditViewModel = hiltViewModel(), shieldViewModel: ShieldViewModel = hiltViewModel(), - viewPasswordViewModel: ViewPasswordViewModel = hiltViewModel() + viewPasswordViewModel: ViewPasswordViewModel = hiltViewModel(), + settingsViewModel: SettingsViewModel = hiltViewModel() ) { val navController = rememberNavController() @@ -197,9 +201,10 @@ fun Navigation( composable(route = Screen.SettingsScreen.name) { SettingsScreen( + activity, navController, themeViewModel, - userViewModel + settingsViewModel ) } diff --git a/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/AccountItems.kt b/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/AccountItems.kt deleted file mode 100644 index 99e562ab..00000000 --- a/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/AccountItems.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.geekymusketeers.uncrack.presentation.account - -import com.geekymusketeers.uncrack.R - -// TODO: Need to change icons for some of the items -enum class AccountItems(val itemsName: String, val icon: Int) { - // Security - CHANGE_MASTER_KEY("Change master password", R.drawable.lock), - BIOMETRIC("Unlock with biometric", R.drawable.fingerprint), - BLOCK_SS("Block screenshots", R.drawable.block_ss), - - //BACKUP - EXPORT_IMPORT("Export/Import", R.drawable.import_export), - BACKUP_RESTORE("Backup/Restore", R.drawable.backup_restore), - - // General - THEME("Theme", R.drawable.themes), - PASSWORD_GENERATOR("Password Generator", R.drawable.generate_password_icon), - INVITE_FRIENDS("Invite Friends", R.drawable.share_app), - RATE_UNCRACK("Rate UnCrack", R.drawable.rating), - SEND_FEEDBACK("Send Feedback", R.drawable.feedback), - PRIVACY_POLICY("Privacy Policy", R.drawable.shield), - - // Danger Zone - LOG_OUT("Log out", R.drawable.logout), - DELETE_ACCOUNT("Delete Account", R.drawable.delete_icon) -} \ No newline at end of file diff --git a/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/profile/ProfileScreen.kt b/app/src/main/java/com/geekymusketeers/uncrack/presentation/profile/ProfileScreen.kt similarity index 98% rename from app/src/main/java/com/geekymusketeers/uncrack/presentation/account/profile/ProfileScreen.kt rename to app/src/main/java/com/geekymusketeers/uncrack/presentation/profile/ProfileScreen.kt index fe9b9d3d..03caa4af 100644 --- a/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/profile/ProfileScreen.kt +++ b/app/src/main/java/com/geekymusketeers/uncrack/presentation/profile/ProfileScreen.kt @@ -1,4 +1,4 @@ -package com.geekymusketeers.uncrack.presentation.account.profile +package com.geekymusketeers.uncrack.presentation.profile import android.content.Intent import android.net.Uri diff --git a/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/SettingsScreen.kt b/app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsScreen.kt similarity index 83% rename from app/src/main/java/com/geekymusketeers/uncrack/presentation/account/SettingsScreen.kt rename to app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsScreen.kt index c70a2028..1800da64 100644 --- a/app/src/main/java/com/geekymusketeers/uncrack/presentation/account/SettingsScreen.kt +++ b/app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsScreen.kt @@ -1,5 +1,7 @@ -package com.geekymusketeers.uncrack.presentation.account +package com.geekymusketeers.uncrack.presentation.settings +import android.app.Activity +import android.content.Intent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -18,13 +20,14 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -33,13 +36,16 @@ import com.geekymusketeers.uncrack.R import com.geekymusketeers.uncrack.components.SettingsItemGroup import com.geekymusketeers.uncrack.components.ThemeDialog import com.geekymusketeers.uncrack.components.UCSettingsCard +import com.geekymusketeers.uncrack.components.UCSwitchCard import com.geekymusketeers.uncrack.components.UCTopAppBar +import com.geekymusketeers.uncrack.data.db.AccountDatabase +import com.geekymusketeers.uncrack.domain.model.Account +import com.geekymusketeers.uncrack.navigation.Screen +import com.geekymusketeers.uncrack.presentation.auth.login.LoginScreens import com.geekymusketeers.uncrack.sharedViewModel.ThemeViewModel -import com.geekymusketeers.uncrack.sharedViewModel.UserViewModel import com.geekymusketeers.uncrack.ui.theme.OnPrimaryContainerLight import com.geekymusketeers.uncrack.ui.theme.OnSurfaceVariantLight import com.geekymusketeers.uncrack.ui.theme.SurfaceVariantLight -import com.geekymusketeers.uncrack.ui.theme.bold18 import com.geekymusketeers.uncrack.ui.theme.bold20 import com.geekymusketeers.uncrack.ui.theme.medium14 import com.geekymusketeers.uncrack.ui.theme.normal16 @@ -47,16 +53,23 @@ import com.geekymusketeers.uncrack.ui.theme.normal16 @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsScreen( + activity: Activity, navController: NavHostController, themeViewModel: ThemeViewModel, - userViewModel: UserViewModel, + settingsViewModel: SettingsViewModel, modifier: Modifier = Modifier ) { - val context = LocalContext.current + val themeStateObserver by themeViewModel.themeState.collectAsState() + val isScreenshotEnabled by settingsViewModel.isScreenshotEnabled.observeAsState(false) + val onLogOutComplete by settingsViewModel.onLogOutComplete.observeAsState(false) var openThemeDialog by remember { mutableStateOf(false) } var openLogoutDialog by remember { mutableStateOf(false) } - val userData = userViewModel.state.value + + if (onLogOutComplete) { + activity.startActivity(Intent(activity, LoginScreens::class.java)) + activity.finish() + } when { openThemeDialog -> { @@ -88,7 +101,7 @@ fun SettingsScreen( confirmButton = { TextButton( onClick = { - // TODO: IMPL the logout logic + settingsViewModel.logout() openLogoutDialog = false }, colors = ButtonDefaults.buttonColors( @@ -156,7 +169,7 @@ fun SettingsScreen( UCSettingsCard( itemName = "Change Master Password", onClick = { - + navController.navigate(Screen.UpdateMasterKeyScreen.name) } ) @@ -165,11 +178,10 @@ fun SettingsScreen( color = SurfaceVariantLight ) - UCSettingsCard( + UCSwitchCard( itemName = stringResource(R.string.unlock_with_biometric), - onClick = { - - } + isChecked = false, + onChecked = {} ) HorizontalDivider( @@ -177,10 +189,11 @@ fun SettingsScreen( color = SurfaceVariantLight ) - UCSettingsCard( + UCSwitchCard( itemName = stringResource(R.string.take_in_app_screenshots), - onClick = { - + isChecked = isScreenshotEnabled, + onChecked = { + settingsViewModel.setScreenshotEnabled(it) } ) } @@ -219,10 +232,11 @@ fun SettingsScreen( Spacer(modifier = Modifier.height(14.dp)) SettingsItemGroup { - UCSettingsCard( + UCSwitchCard( itemName = stringResource(R.string.theme), - onClick = { - + isChecked = themeStateObserver.isDarkMode, + onChecked = { + themeViewModel.toggleTheme() } ) } diff --git a/app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsViewModel.kt b/app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsViewModel.kt new file mode 100644 index 00000000..cb0c6d06 --- /dev/null +++ b/app/src/main/java/com/geekymusketeers/uncrack/presentation/settings/SettingsViewModel.kt @@ -0,0 +1,24 @@ +package com.geekymusketeers.uncrack.presentation.settings + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.geekymusketeers.uncrack.util.runIO +import com.google.firebase.auth.FirebaseAuth +import javax.inject.Inject + +class SettingsViewModel @Inject constructor(): ViewModel() { + + val onLogOutComplete = MutableLiveData() + private val _isScreenshotEnabled = MutableLiveData(false) + val isScreenshotEnabled: LiveData get() = _isScreenshotEnabled + + fun setScreenshotEnabled(enabled: Boolean) { + _isScreenshotEnabled.value = enabled + } + + fun logout() = runIO { + FirebaseAuth.getInstance().signOut() + onLogOutComplete.postValue(true) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/geekymusketeers/uncrack/sharedViewModel/ThemeViewModel.kt b/app/src/main/java/com/geekymusketeers/uncrack/sharedViewModel/ThemeViewModel.kt index 54d5ea10..e95ea0f0 100644 --- a/app/src/main/java/com/geekymusketeers/uncrack/sharedViewModel/ThemeViewModel.kt +++ b/app/src/main/java/com/geekymusketeers/uncrack/sharedViewModel/ThemeViewModel.kt @@ -47,10 +47,4 @@ class ThemeViewModel @Inject constructor( } } } - - fun blockScreenShort() = runIO { - dataStore.edit { preferences -> - preferences[IS_SS_BLOCK_KEY] = !(preferences[IS_SS_BLOCK_KEY] ?: false) - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/geekymusketeers/uncrack/ui/theme/Theme.kt b/app/src/main/java/com/geekymusketeers/uncrack/ui/theme/Theme.kt index 228a8302..82b4061f 100644 --- a/app/src/main/java/com/geekymusketeers/uncrack/ui/theme/Theme.kt +++ b/app/src/main/java/com/geekymusketeers/uncrack/ui/theme/Theme.kt @@ -45,9 +45,8 @@ private val LightColorPalette = lightColorScheme( @Composable fun UnCrackTheme( - darkTheme: Boolean = isSystemInDarkTheme(), themeViewModel: ThemeViewModel = hiltViewModel(), - dynamicColor: Boolean = true, + dynamicColor: Boolean = false, content: @Composable () -> Unit ) { val themeState by themeViewModel.themeState.collectAsState()