mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-30 22:05:19 +00:00
Add key manager UI
This commit is contained in:
@@ -27,6 +27,14 @@ android {
|
|||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
composeOptions {
|
||||||
|
useLiveLiterals = false
|
||||||
|
kotlinCompilerExtensionVersion = libs.compose.compiler.get().versionConstraint.requiredVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace = "app.passwordstore"
|
namespace = "app.passwordstore"
|
||||||
|
|
||||||
lint {
|
lint {
|
||||||
@@ -52,6 +60,7 @@ dependencies {
|
|||||||
implementation(projects.passgen.random)
|
implementation(projects.passgen.random)
|
||||||
implementation(projects.uiCompose)
|
implementation(projects.uiCompose)
|
||||||
implementation(libs.androidx.activity.ktx)
|
implementation(libs.androidx.activity.ktx)
|
||||||
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
implementation(libs.androidx.autofill)
|
implementation(libs.androidx.autofill)
|
||||||
implementation(libs.androidx.biometricKtx)
|
implementation(libs.androidx.biometricKtx)
|
||||||
|
@@ -163,6 +163,11 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".ui.pgp.PGPKeyImportActivity"
|
android:name=".ui.pgp.PGPKeyImportActivity"
|
||||||
android:theme="@style/NoBackgroundThemeM3" />
|
android:theme="@style/NoBackgroundThemeM3" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.pgp.PGPKeyListActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:label="@string/activity_label_pgp_key_manager"
|
||||||
|
android:parentActivityName=".ui.settings.SettingsActivity" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
|
@@ -0,0 +1,44 @@
|
|||||||
|
package app.passwordstore.ui.pgp
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import app.passwordstore.ui.compose.theme.APSTheme
|
||||||
|
import app.passwordstore.util.viewmodel.PGPKeyListViewModel
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
class PGPKeyListActivity : ComponentActivity() {
|
||||||
|
|
||||||
|
private val viewModel: PGPKeyListViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
APSTheme {
|
||||||
|
Scaffold { paddingValues ->
|
||||||
|
PGPKeyList(viewModel = viewModel, modifier = Modifier.padding(paddingValues))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PGPKeyList(
|
||||||
|
viewModel: PGPKeyListViewModel,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
KeyList(
|
||||||
|
identifiers = viewModel.keys,
|
||||||
|
onItemClick = viewModel::deleteKey,
|
||||||
|
modifier = modifier,
|
||||||
|
)
|
||||||
|
}
|
@@ -7,6 +7,7 @@ package app.passwordstore.ui.settings
|
|||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import app.passwordstore.ui.pgp.PGPKeyImportActivity
|
import app.passwordstore.ui.pgp.PGPKeyImportActivity
|
||||||
|
import app.passwordstore.ui.pgp.PGPKeyListActivity
|
||||||
import app.passwordstore.util.extensions.launchActivity
|
import app.passwordstore.util.extensions.launchActivity
|
||||||
import de.Maxr1998.modernpreferences.PreferenceScreen
|
import de.Maxr1998.modernpreferences.PreferenceScreen
|
||||||
import de.Maxr1998.modernpreferences.helpers.onClick
|
import de.Maxr1998.modernpreferences.helpers.onClick
|
||||||
@@ -24,6 +25,14 @@ class PGPSettings(private val activity: FragmentActivity) : SettingsProvider {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pref("__") {
|
||||||
|
title = "Key manager"
|
||||||
|
persistent = false
|
||||||
|
onClick {
|
||||||
|
activity.launchActivity(PGPKeyListActivity::class.java)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ import android.util.Base64
|
|||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.autofill.AutofillManager
|
import android.view.autofill.AutofillManager
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
@@ -120,7 +121,7 @@ fun FragmentActivity.snackbar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Launch an activity denoted by [clazz]. */
|
/** Launch an activity denoted by [clazz]. */
|
||||||
fun <T : FragmentActivity> FragmentActivity.launchActivity(clazz: Class<T>) {
|
fun <T : ComponentActivity> ComponentActivity.launchActivity(clazz: Class<T>) {
|
||||||
startActivity(Intent(this, clazz))
|
startActivity(Intent(this, clazz))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
package app.passwordstore.util.viewmodel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import app.passwordstore.crypto.GpgIdentifier
|
||||||
|
import app.passwordstore.crypto.KeyUtils
|
||||||
|
import app.passwordstore.crypto.PGPKeyManager
|
||||||
|
import com.github.michaelbull.result.Err
|
||||||
|
import com.github.michaelbull.result.Ok
|
||||||
|
import com.github.michaelbull.result.map
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class PGPKeyListViewModel @Inject constructor(private val keyManager: PGPKeyManager) : ViewModel() {
|
||||||
|
var keys: List<GpgIdentifier> by mutableStateOf(emptyList())
|
||||||
|
|
||||||
|
init {
|
||||||
|
getKeys()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getKeys() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
when (
|
||||||
|
val result =
|
||||||
|
keyManager.getAllKeys().map { keys ->
|
||||||
|
keys.mapNotNull { key -> KeyUtils.tryGetEmail(key) }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
is Ok -> keys = result.value
|
||||||
|
is Err -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteKey(identifier: GpgIdentifier) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
keyManager.removeKey(identifier)
|
||||||
|
getKeys()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -378,5 +378,6 @@
|
|||||||
<string name="pref_category_pgp_title">PGP settings</string>
|
<string name="pref_category_pgp_title">PGP settings</string>
|
||||||
<string name="pwgen_some_error_occurred">Some error occurred</string>
|
<string name="pwgen_some_error_occurred">Some error occurred</string>
|
||||||
<string name="git_run_gc_job">Run garbage collection job</string>
|
<string name="git_run_gc_job">Run garbage collection job</string>
|
||||||
|
<string name="activity_label_pgp_key_manager">PGP Key Manager</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Reference in New Issue
Block a user