feat: wire up key import functionality
This commit is contained in:
parent
a96f24ac96
commit
c4edf7f0e6
6 changed files with 105 additions and 25 deletions
|
@ -9,7 +9,9 @@ import android.os.Bundle
|
|||
import androidx.activity.addCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import app.passwordstore.R
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class OnboardingActivity : AppCompatActivity(R.layout.activity_onboarding) {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
|
@ -5,21 +5,68 @@
|
|||
|
||||
package app.passwordstore.ui.onboarding.fragments
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.edit
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.data.repo.PasswordRepository
|
||||
import app.passwordstore.databinding.FragmentKeySelectionBinding
|
||||
import app.passwordstore.injection.prefs.SettingsPreferences
|
||||
import app.passwordstore.ui.pgp.PGPKeyListActivity
|
||||
import app.passwordstore.util.coroutines.DispatcherProvider
|
||||
import app.passwordstore.util.extensions.commitChange
|
||||
import app.passwordstore.util.extensions.finish
|
||||
import app.passwordstore.util.extensions.snackbar
|
||||
import app.passwordstore.util.extensions.viewBinding
|
||||
import app.passwordstore.util.settings.PreferenceKeys
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@AndroidEntryPoint
|
||||
class KeySelectionFragment : Fragment(R.layout.fragment_key_selection) {
|
||||
|
||||
@Inject @SettingsPreferences lateinit var settings: SharedPreferences
|
||||
@Inject lateinit var dispatcherProvider: DispatcherProvider
|
||||
private val binding by viewBinding(FragmentKeySelectionBinding::bind)
|
||||
private val gpgKeySelectAction =
|
||||
registerForActivityResult(StartActivityForResult()) { result ->
|
||||
if (result.resultCode == AppCompatActivity.RESULT_OK) {
|
||||
val data = result.data ?: return@registerForActivityResult
|
||||
val selectedKey =
|
||||
data.getStringExtra(PGPKeyListActivity.EXTRA_SELECTED_KEY)
|
||||
?: return@registerForActivityResult
|
||||
lifecycleScope.launch {
|
||||
withContext(dispatcherProvider.io()) {
|
||||
val gpgIdentifierFile = File(PasswordRepository.getRepositoryDirectory(), ".gpg-id")
|
||||
gpgIdentifierFile.writeText(selectedKey)
|
||||
}
|
||||
settings.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) }
|
||||
requireActivity()
|
||||
.commitChange(getString(R.string.git_commit_gpg_id, getString(R.string.app_name)))
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
requireActivity()
|
||||
.snackbar(
|
||||
message = getString(R.string.gpg_key_select_mandatory),
|
||||
length = Snackbar.LENGTH_LONG,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.selectKey.setOnClickListener {
|
||||
// TODO(msfjarvis): Restore this functionality
|
||||
// gpgKeySelectAction.launch(Intent(requireContext(), GetKeyIdsActivity::class.java))
|
||||
gpgKeySelectAction.launch(PGPKeyListActivity.newSelectionActivity(requireContext()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package app.passwordstore.ui.pgp
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
@ -28,12 +29,14 @@ import androidx.compose.ui.unit.dp
|
|||
import app.passwordstore.R
|
||||
import app.passwordstore.crypto.GpgIdentifier
|
||||
import app.passwordstore.ui.compose.theme.APSThemePreview
|
||||
import app.passwordstore.util.extensions.conditional
|
||||
|
||||
@Composable
|
||||
fun KeyList(
|
||||
identifiers: List<GpgIdentifier>,
|
||||
onItemClick: (identifier: GpgIdentifier) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
onKeySelected: ((identifier: GpgIdentifier) -> Unit)? = null,
|
||||
) {
|
||||
if (identifiers.isEmpty()) {
|
||||
Column(
|
||||
|
@ -50,7 +53,7 @@ fun KeyList(
|
|||
} else {
|
||||
LazyColumn(modifier = modifier) {
|
||||
items(identifiers) { identifier ->
|
||||
KeyItem(identifier = identifier, onItemClick = onItemClick)
|
||||
KeyItem(identifier = identifier, onItemClick = onItemClick, onKeySelected = onKeySelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +64,7 @@ private fun KeyItem(
|
|||
identifier: GpgIdentifier,
|
||||
onItemClick: (identifier: GpgIdentifier) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
onKeySelected: ((identifier: GpgIdentifier) -> Unit)? = null,
|
||||
) {
|
||||
var isDeleting by remember { mutableStateOf(false) }
|
||||
DeleteConfirmationDialog(
|
||||
|
@ -77,11 +81,15 @@ private fun KeyItem(
|
|||
is GpgIdentifier.UserId -> identifier.email
|
||||
}
|
||||
Row(
|
||||
modifier = modifier.padding(16.dp).fillMaxWidth(),
|
||||
modifier =
|
||||
modifier.padding(16.dp).fillMaxWidth().conditional(onKeySelected != null) {
|
||||
clickable { onKeySelected?.invoke(identifier) }
|
||||
},
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(text = label)
|
||||
if (onKeySelected == null) {
|
||||
IconButton(onClick = { isDeleting = true }) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_delete_24dp),
|
||||
|
@ -89,6 +97,7 @@ private fun KeyItem(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package app.passwordstore.ui.pgp
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
|
@ -12,12 +13,10 @@ import androidx.compose.material3.FloatingActionButton
|
|||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.ui.APSAppBar
|
||||
import app.passwordstore.ui.compose.theme.APSTheme
|
||||
|
@ -39,6 +38,7 @@ class PGPKeyListActivity : ComponentActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val isSelecting = intent.extras?.getBoolean(EXTRA_KEY_SELECTION) ?: false
|
||||
setContent {
|
||||
val context = LocalContext.current
|
||||
APSTheme(colors = decideColorScheme(context)) {
|
||||
|
@ -62,21 +62,33 @@ class PGPKeyListActivity : ComponentActivity() {
|
|||
}
|
||||
}
|
||||
) { paddingValues ->
|
||||
PGPKeyList(viewModel = viewModel, modifier = Modifier.padding(paddingValues))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PGPKeyList(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: PGPKeyListViewModel = viewModel(),
|
||||
) {
|
||||
KeyList(
|
||||
identifiers = viewModel.keys,
|
||||
onItemClick = viewModel::deleteKey,
|
||||
modifier = modifier,
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
onKeySelected =
|
||||
if (isSelecting) {
|
||||
{ identifier ->
|
||||
val result = Intent()
|
||||
result.putExtra(EXTRA_SELECTED_KEY, identifier.toString())
|
||||
setResult(RESULT_OK, result)
|
||||
finish()
|
||||
}
|
||||
} else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_SELECTED_KEY = "SELECTED_KEY"
|
||||
private const val EXTRA_KEY_SELECTION = "KEY_SELECTION_MODE"
|
||||
|
||||
fun newSelectionActivity(context: Context): Intent {
|
||||
val intent = Intent(context, PGPKeyListActivity::class.java)
|
||||
intent.putExtra(EXTRA_KEY_SELECTION, true)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.view.View
|
|||
import android.view.autofill.AutofillManager
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
|
@ -153,3 +154,12 @@ fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): Ap
|
|||
@Suppress("DEPRECATION") getApplicationInfo(packageName, flags)
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows conditionally applying the given [modifier] if [isEnabled] is `true`. */
|
||||
fun Modifier.conditional(isEnabled: Boolean, modifier: Modifier.() -> Modifier): Modifier {
|
||||
return if (isEnabled) {
|
||||
then(modifier())
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<string name="git_commit_remove_text">Remove %1$s from store.</string>
|
||||
<string name="git_commit_move_text">Rename %1$s to %2$s.</string>
|
||||
<string name="git_commit_move_multiple_text">Move multiple passwords to %1$s.</string>
|
||||
<string name="git_commit_gpg_id">Initialize GPG IDs in %1$s.</string>
|
||||
|
||||
<!-- PGPHandler -->
|
||||
<string name="clipboard_copied_text">Copied to clipboard</string>
|
||||
|
@ -318,9 +319,8 @@
|
|||
<string name="git_break_out_of_detached_success">There was a conflict when trying to rebase. Your local %1$s branch was pushed to another branch named %2$s\n Use this branch to resolve conflict on your computer</string>
|
||||
<string name="git_break_out_of_detached_unneeded">The repository is not rebasing, no need to push to another branch</string>
|
||||
|
||||
<!-- OpenKeychain not installed -->
|
||||
|
||||
<!-- GPG key selection in folder creation -->
|
||||
<string name="gpg_key_select_mandatory">Selecting a GPG key is necessary to proceed</string>
|
||||
<string name="folder_creation_err_file_exists">A file by that name already exists</string>
|
||||
<string name="folder_creation_err_folder_exists">A folder by that name already exists</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue