Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
Revert "Initial ui rewrite"
Browse files Browse the repository at this point in the history
This reverts commit 2b2933d.
  • Loading branch information
M3DZIK committed Oct 19, 2024
1 parent 43586b6 commit 4684a5c
Show file tree
Hide file tree
Showing 82 changed files with 5,521 additions and 1,821 deletions.
45 changes: 43 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ plugins {
alias(libs.plugins.dagger.hilt)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.compose.compiler)
}

Expand Down Expand Up @@ -69,14 +71,53 @@ android {
}

dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)

implementation(libs.compose.material.icons)
implementation(libs.compose.material3)
implementation(libs.compose.navigation)
implementation(libs.compose.ui)

implementation(libs.accompanist.drawablepainter)

implementation(libs.androidx.biometric.ktx)

// used for calling `onResume` and locking vault after X minutes
implementation(libs.compose.lifecycle.runtime)

implementation(projects.databaseLogic)

// dagger
implementation(libs.dagger.hilt)
implementation(libs.hilt.navigation.compose)
ksp(libs.dagger.hilt.compiler)

implementation(projects.uiLogic)
implementation(projects.databaseLogic)
implementation(libs.coil.compose)

implementation(libs.librepass.client)
implementation(libs.otp)

implementation(libs.kotlinx.coroutines)
implementation(libs.kotlinx.serialization.json)

implementation(projects.common)
implementation(projects.businessLogic)

// for splash screen with material3 and dynamic color
implementation(libs.google.material)

implementation(libs.zxing.android) { isTransitive = false }
implementation(libs.zxing)

implementation(libs.medzik.android.compose)
implementation(libs.medzik.android.crypto)
implementation(libs.medzik.android.utils)

// for testing
debugImplementation(libs.compose.ui.test.manifest)

// for preview support
debugImplementation(libs.compose.ui.tooling)
implementation(libs.compose.ui.tooling.preview)
}
64 changes: 40 additions & 24 deletions app/src/main/java/dev/medzik/librepass/android/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.fragment.app.FragmentActivity
import androidx.navigation.NavController
import dagger.hilt.android.AndroidEntryPoint
import dev.medzik.android.utils.openEmailApplication
import dev.medzik.librepass.android.business.VaultCache
import dev.medzik.librepass.android.common.popUpToDestination
import dev.medzik.librepass.android.database.Repository
import dev.medzik.librepass.android.ui.LibrePassNavigation
import dev.medzik.librepass.android.ui.screens.auth.Unlock
import dev.medzik.librepass.android.ui.theme.LibrePassTheme
import javax.inject.Inject

Expand All @@ -16,6 +22,9 @@ class MainActivity : FragmentActivity() {
@Inject
lateinit var repository: Repository

@Inject
lateinit var vault: VaultCache

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand All @@ -25,42 +34,49 @@ class MainActivity : FragmentActivity() {
Thread.setDefaultUncaughtExceptionHandler { _, e ->
Log.e("LibrePass", "Uncaught exception", e)

// TODO
openEmailApplication(
email = "[email protected]",
subject = "[Bug] [Android]: ",
body = "<A few words about the error>\n\n\n---- Stack trace for debugging ----\n\n${Log.getStackTraceString(e)}"
)

finish()
}

MigrationsManager.run(this, repository)

// retrieves aes key for vault decryption if key is valid
// vault.getSecretsIfNotExpired(this)
vault.getSecretsIfNotExpired(this)

setContent {
LibrePassTheme {
LibrePassTheme(
darkTheme = isSystemInDarkTheme(),
dynamicColor = true
) {
LibrePassNavigation()
}
}
}

// override fun onPause() {
// super.onPause()
//
// // check if user is logged
// if (repository.credentials.get() == null) return
//
// vault.saveVaultExpiration(this)
// }
//
// /** Called from [LibrePassNavigation]. */
// fun onResume(navController: NavController) {
// // check if user is logged
// if (repository.credentials.get() == null) return
//
// val expired = vault.handleExpiration(this)
// if (expired) {
// navController.navigate(Unlock) {
// popUpToDestination(Unlock)
// }
// }
// }
override fun onPause() {
super.onPause()

// check if user is logged
if (repository.credentials.get() == null) return

vault.saveVaultExpiration(this)
}

/** Called from [LibrePassNavigation]. */
fun onResume(navController: NavController) {
// check if user is logged
if (repository.credentials.get() == null) return

val expired = vault.handleExpiration(this)
if (expired) {
navController.navigate(Unlock) {
popUpToDestination(Unlock)
}
}
}
}
129 changes: 129 additions & 0 deletions app/src/main/java/dev/medzik/librepass/android/ui/Navigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package dev.medzik.librepass.android.ui

import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.currentStateAsState
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import dev.medzik.android.compose.icons.TopAppBarBackIcon
import dev.medzik.android.compose.navigation.NavigationAnimations
import dev.medzik.librepass.android.MainActivity
import dev.medzik.librepass.android.common.LibrePassViewModel
import dev.medzik.librepass.android.ui.components.TopBar
import dev.medzik.librepass.android.ui.screens.Welcome
import dev.medzik.librepass.android.ui.screens.WelcomeScreen
import dev.medzik.librepass.android.ui.screens.auth.Unlock
import dev.medzik.librepass.android.ui.screens.auth.authNavigation
import dev.medzik.librepass.android.ui.screens.settings.settingsNavigation
import dev.medzik.librepass.android.ui.screens.vault.Vault
import dev.medzik.librepass.android.ui.screens.vault.vaultNavigation

@Composable
fun LibrePassNavigation(viewModel: LibrePassViewModel = hiltViewModel()) {
val context = LocalContext.current
val navController = rememberNavController()

// Lifecycle events handler.
// This calls the `onResume` function from MainActivity when the application is resumed.
// This is used to lock the vault after X minutes of application sleep in memory.
val lifecycleOwner = LocalLifecycleOwner.current
val lifecycleState by lifecycleOwner.lifecycle.currentStateAsState()
LaunchedEffect(lifecycleState) {
when (lifecycleState) {
// when the application was resumed
Lifecycle.State.RESUMED -> {
// calls the `onResume` function from MainActivity
(context as MainActivity).onResume(navController)
}
// ignore any other lifecycle state
else -> {}
}
}

fun getStartRoute(): Any {
// if a user is not logged in, show welcome screen
viewModel.credentialRepository.get() ?: return Welcome

// if user secrets are not set, show unlock screen
if (viewModel.vault.aesKey.isEmpty())
return Unlock

// else where the user secrets are set, show vault screen
return Vault
}

NavHost(
navController,
startDestination = remember { getStartRoute() },
modifier = Modifier.imePadding(),
enterTransition = {
NavigationAnimations.enterTransition()
},
exitTransition = {
NavigationAnimations.exitTransition()
},
popEnterTransition = {
NavigationAnimations.popEnterTransition()
},
popExitTransition = {
NavigationAnimations.popExitTransition()
}
) {
composable<Welcome> {
WelcomeScreen(navController)
}

authNavigation(navController)

vaultNavigation(navController)

settingsNavigation(navController)
}
}

@Composable
fun DefaultScaffold(
topBar: @Composable () -> Unit = {},
floatingActionButton: @Composable () -> Unit = {},
horizontalPadding: Boolean = true,
composable: @Composable () -> Unit
) {
Scaffold(
topBar = { topBar() },
floatingActionButton = { floatingActionButton() }
) { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = if (horizontalPadding) 16.dp else 0.dp)
) {
composable()
}
}
}

@Composable
fun TopBarWithBack(@StringRes title: Int, navController: NavController) {
TopBar(
title = stringResource(title),
navigationIcon = { TopAppBarBackIcon(navController) }
)
}
Loading

0 comments on commit 4684a5c

Please sign in to comment.