Skip to content

Commit

Permalink
Merge pull request #200 from uncrack-vault/biomertrci_auth
Browse files Browse the repository at this point in the history
Biometric Auth
  • Loading branch information
aritra-tech authored Feb 1, 2025
2 parents 3aa9d9f + 8b9d5c1 commit 18d1160
Show file tree
Hide file tree
Showing 29 changed files with 914 additions and 75 deletions.
1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

384 changes: 384 additions & 0 deletions .idea/other.xml

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ dependencies {
implementation("androidx.hilt:hilt-navigation-compose:1.2.0")

// Datastore
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("androidx.datastore:datastore-preferences:1.1.2")

// Lottie Animation
implementation("com.airbnb.android:lottie-compose:5.0.3")
Expand Down Expand Up @@ -163,4 +163,6 @@ dependencies {

// BCrypt
implementation("org.mindrot:jbcrypt:0.4")

implementation("androidx.biometric:biometric:1.2.0-alpha05")
}
Binary file added app/release/app-release.aab
Binary file not shown.
37 changes: 36 additions & 1 deletion app/src/main/java/com/aritradas/uncrack/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ import androidx.annotation.RequiresApi
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.core.view.WindowCompat
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.aritradas.uncrack.navigation.Navigation
import com.aritradas.uncrack.presentation.settings.SettingsViewModel
import com.aritradas.uncrack.sharedViewModel.SharedViewModel
import com.aritradas.uncrack.ui.theme.UnCrackTheme
import com.aritradas.uncrack.util.AppBioMetricManager
import com.aritradas.uncrack.util.NetworkConnectivityObserver
import com.google.android.gms.tasks.Task
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
Expand All @@ -25,11 +31,18 @@ import com.google.android.play.core.appupdate.AppUpdateOptions
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.UpdateAvailability
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
class MainActivity : FragmentActivity() {

private val settingsViewModel: SettingsViewModel by viewModels()
private val viewModel: SharedViewModel by viewModels()

@Inject
lateinit var appBioMetricManager: AppBioMetricManager

private val activityResultLauncher = registerForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
Expand Down Expand Up @@ -75,6 +88,28 @@ class MainActivity : ComponentActivity() {
Navigation(this, connectivityObserver)
}
}

setObserver()
}

private fun setObserver() {
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.initAuth.collect { value ->
if (value && viewModel.loading.value) {
viewModel.showBiometricPrompt(this@MainActivity)
}
}
}
}

lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.finishActivity.collect { value ->
if (value) finish()
}
}
}
}

private fun checkForAppUpdate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.aritradas.uncrack.ui.theme.BackgroundLight
import com.aritradas.uncrack.ui.theme.SurfaceVariantLight

@Composable
fun SettingsItemGroup(
Expand All @@ -21,9 +22,9 @@ fun SettingsItemGroup(
Column(
modifier = modifier
.widthIn(max = 500.dp)
.padding(start = 12.dp, end = 12.dp)
.clip(RoundedCornerShape(8.dp))
.background(BackgroundLight),
.padding(horizontal = 12.dp)
.clip(RoundedCornerShape(10.dp))
.background(SurfaceVariantLight),
horizontalAlignment = Alignment.CenterHorizontally
) {
columnScope()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ class DataStoreUtil @Inject constructor(context: Context) {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("settings")
val IS_DARK_MODE_KEY = booleanPreferencesKey("dark_mode")
val IS_SS_BLOCK_KEY = booleanPreferencesKey("ss_block")
val IS_BIOMETRIC_AUTH_SET_KEY = booleanPreferencesKey("biometric_auth")
}
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/aritradas/uncrack/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
object AppModule {

@Provides
fun provideContext(@ApplicationContext context: Context): Context {
return context
}

@Provides
fun provideDataStoreUtil(@ApplicationContext context: Context): DataStoreUtil =
DataStoreUtil(context)
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/com/aritradas/uncrack/di/BioMetricUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.aritradas.uncrack.di

import android.content.Context
import com.aritradas.uncrack.util.AppBioMetricManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent

@Module
@InstallIn(ViewModelComponent::class)
class BioMetricUtil {

@Provides
fun provideAppBioMetricManager(context: Context): AppBioMetricManager {
return AppBioMetricManager(context)
}
}
22 changes: 22 additions & 0 deletions app/src/main/java/com/aritradas/uncrack/di/ViewModelModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.aritradas.uncrack.di

import com.aritradas.uncrack.data.datastore.DataStoreUtil
import com.aritradas.uncrack.sharedViewModel.SharedViewModel
import com.aritradas.uncrack.util.AppBioMetricManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent

@Module
@InstallIn(ViewModelComponent::class)
class ViewModelModule {

@Provides
fun provideMainViewModel(
bioMetricManager: AppBioMetricManager,
dataStoreUtil: DataStoreUtil,
): SharedViewModel {
return SharedViewModel(bioMetricManager, dataStoreUtil)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import com.aritradas.uncrack.ui.theme.FadeOut
import com.aritradas.uncrack.ui.theme.OnPrimaryContainerLight
import com.aritradas.uncrack.ui.theme.OnSurfaceVariantLight
import com.aritradas.uncrack.ui.theme.PrimaryDark
import com.aritradas.uncrack.ui.theme.SurfaceVariantLight
import com.aritradas.uncrack.util.BackPressHandler
import com.aritradas.uncrack.util.ConnectivityObserver
import kotlinx.collections.immutable.ImmutableList
Expand Down Expand Up @@ -156,6 +157,7 @@ fun Navigation(

composable(Screen.SignUpScreen.name) {
SignupScreen(
navController,
authViewModel,
connectivityObserver,
onSignUp = {
Expand Down Expand Up @@ -271,7 +273,6 @@ fun Navigation(

composable(route = Screen.SettingsScreen.name) {
SettingsScreen(
activity,
navController,
settingsViewModel
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.aritradas.uncrack.presentation.auth.login

import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -47,6 +48,7 @@ import com.aritradas.uncrack.components.UCButton
import com.aritradas.uncrack.components.UCTextField
import com.aritradas.uncrack.navigation.Screen
import com.aritradas.uncrack.presentation.auth.AuthViewModel
import com.aritradas.uncrack.ui.theme.BackgroundLight
import com.aritradas.uncrack.ui.theme.DMSansFontFamily
import com.aritradas.uncrack.ui.theme.OnPrimaryContainerLight
import com.aritradas.uncrack.ui.theme.PrimaryLight
Expand Down Expand Up @@ -105,6 +107,7 @@ fun LoginScreen(
Column(
modifier = Modifier
.fillMaxSize()
.background(BackgroundLight)
.padding(paddingValues)
.padding(16.dp)
) {
Expand Down Expand Up @@ -202,10 +205,6 @@ fun LoginScreen(
}
}
}

if (isLoading) {
ProgressDialog {}
}
}
else -> {
NoInternetScreen()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.aritradas.uncrack.presentation.auth.signup

import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -45,6 +46,7 @@ import com.aritradas.uncrack.components.UCButton
import com.aritradas.uncrack.components.UCTextField
import com.aritradas.uncrack.navigation.Screen
import com.aritradas.uncrack.presentation.auth.AuthViewModel
import com.aritradas.uncrack.ui.theme.BackgroundLight
import com.aritradas.uncrack.ui.theme.DMSansFontFamily
import com.aritradas.uncrack.ui.theme.OnPrimaryContainerLight
import com.aritradas.uncrack.ui.theme.PrimaryLight
Expand All @@ -60,6 +62,7 @@ import kotlinx.coroutines.flow.collectLatest

@Composable
fun SignupScreen(
navController: NavController,
authViewModel: AuthViewModel,
connectivityObserver: ConnectivityObserver,
modifier: Modifier = Modifier,
Expand Down Expand Up @@ -106,9 +109,6 @@ fun SignupScreen(
}
}

if (isLoading) {
ProgressDialog {}
}

when(networkStatus) {
ConnectivityObserver.Status.Available -> {
Expand All @@ -118,6 +118,7 @@ fun SignupScreen(
Column(
modifier = Modifier
.fillMaxSize()
.background(BackgroundLight)
.padding(paddingValues)
.padding(16.dp)
) {
Expand Down Expand Up @@ -229,7 +230,7 @@ fun SignupScreen(

Text(
modifier = Modifier.clickable {

navController.navigate(Screen.LoginScreen.name)
},
text = stringResource(id = R.string.login),
style = medium16.copy(color = PrimaryLight)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,34 @@ import com.aritradas.uncrack.components.UCButton
import com.aritradas.uncrack.components.UCTextField
import com.aritradas.uncrack.navigation.Screen
import com.aritradas.uncrack.presentation.masterKey.KeyViewModel
import com.aritradas.uncrack.ui.theme.BackgroundLight
import com.aritradas.uncrack.ui.theme.SurfaceVariantLight
import com.aritradas.uncrack.ui.theme.bold30
import kotlinx.coroutines.delay

@Composable
fun ConfirmMasterKeyScreen(
navController: NavController,
modifier: Modifier = Modifier,
masterKeyViewModel: KeyViewModel = hiltViewModel()
) {

val context = LocalContext.current
var confirmMasterKey by remember { mutableStateOf("") }
var passwordVisibility by remember { mutableStateOf(false) }
var isLoading by remember { mutableStateOf(false) }
val savedMasterKey = masterKeyViewModel.keyModel.password

LaunchedEffect(Unit) {
masterKeyViewModel.getMasterKey()
}

LaunchedEffect(isLoading) {
if (isLoading) {
delay(2000)
isLoading = false
navController.navigate(Screen.VaultScreen.name)
}
}

Scaffold(
modifier.fillMaxSize()
) { paddingValues ->
Expand All @@ -63,7 +72,7 @@ fun ConfirmMasterKeyScreen(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.background(SurfaceVariantLight)
.background(BackgroundLight)
.padding(16.dp)
) {

Expand Down Expand Up @@ -98,10 +107,7 @@ fun ConfirmMasterKeyScreen(
R.string.hide_password
)


IconButton(onClick =
{ passwordVisibility = passwordVisibility.not() }
) {
IconButton(onClick = { passwordVisibility = passwordVisibility.not() }) {
Icon(
modifier = Modifier.size(24.dp),
painter = image,
Expand All @@ -117,8 +123,12 @@ fun ConfirmMasterKeyScreen(
modifier = Modifier
.fillMaxWidth(),
text = stringResource(R.string.unlock_uncrack),
isLoading = isLoading,
loadingText = "Unlocking...",
onClick = {
navController.navigate(Screen.VaultScreen.name)
if (savedMasterKey == confirmMasterKey) {
isLoading = true
}
},
enabled = savedMasterKey == confirmMasterKey
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import com.aritradas.uncrack.components.UCTextField
import com.aritradas.uncrack.domain.model.Key
import com.aritradas.uncrack.navigation.Screen
import com.aritradas.uncrack.presentation.masterKey.KeyViewModel
import com.aritradas.uncrack.ui.theme.BackgroundLight
import com.aritradas.uncrack.ui.theme.OnPrimaryContainerLight
import com.aritradas.uncrack.ui.theme.SurfaceTintLight
import com.aritradas.uncrack.ui.theme.SurfaceVariantLight
Expand Down Expand Up @@ -66,7 +67,7 @@ fun CreateMasterKeyScreen(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.background(SurfaceVariantLight)
.background(BackgroundLight)
.padding(16.dp)
) {
Text(
Expand Down
Loading

0 comments on commit 18d1160

Please sign in to comment.