mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-31 14:25:28 +00:00
Add option to automatically sync repository on app launch (#1137)
* Add option to automatically sync repository on app launch Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Pull repo if user is not authenticated Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Address review comments Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Hijack incoming intent rather than copying it Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Initialize password repository before using it Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
@@ -42,8 +42,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".LaunchActivity"
|
android:name=".LaunchActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name">
|
||||||
android:theme="@style/NoBackgroundTheme">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
@@ -4,20 +4,34 @@
|
|||||||
*/
|
*/
|
||||||
package com.zeapo.pwdstore
|
package com.zeapo.pwdstore
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.github.michaelbull.result.fold
|
||||||
import com.zeapo.pwdstore.crypto.DecryptActivity
|
import com.zeapo.pwdstore.crypto.DecryptActivity
|
||||||
|
import com.zeapo.pwdstore.databinding.ActivityLaunchBinding
|
||||||
|
import com.zeapo.pwdstore.git.BaseGitActivity
|
||||||
|
import com.zeapo.pwdstore.git.config.AuthMode
|
||||||
|
import com.zeapo.pwdstore.git.config.GitSettings
|
||||||
import com.zeapo.pwdstore.utils.BiometricAuthenticator
|
import com.zeapo.pwdstore.utils.BiometricAuthenticator
|
||||||
|
import com.zeapo.pwdstore.utils.PasswordRepository
|
||||||
import com.zeapo.pwdstore.utils.PreferenceKeys
|
import com.zeapo.pwdstore.utils.PreferenceKeys
|
||||||
import com.zeapo.pwdstore.utils.sharedPrefs
|
import com.zeapo.pwdstore.utils.sharedPrefs
|
||||||
|
import com.zeapo.pwdstore.utils.viewBinding
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class LaunchActivity : AppCompatActivity() {
|
class LaunchActivity : BaseGitActivity() {
|
||||||
|
|
||||||
|
private val binding by viewBinding(ActivityLaunchBinding::inflate)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(binding.root)
|
||||||
|
supportActionBar?.hide()
|
||||||
val prefs = sharedPrefs
|
val prefs = sharedPrefs
|
||||||
if (prefs.getBoolean(PreferenceKeys.BIOMETRIC_AUTH, false)) {
|
if (prefs.getBoolean(PreferenceKeys.BIOMETRIC_AUTH, false)) {
|
||||||
BiometricAuthenticator.authenticate(this) {
|
BiometricAuthenticator.authenticate(this) {
|
||||||
@@ -40,18 +54,38 @@ class LaunchActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startTargetActivity(noAuth: Boolean) {
|
private fun startTargetActivity(noAuth: Boolean) {
|
||||||
val intentToStart = if (intent.action == ACTION_DECRYPT_PASS)
|
if (intent.action == ACTION_DECRYPT_PASS) {
|
||||||
Intent(this, DecryptActivity::class.java).apply {
|
intent.component = ComponentName(this, DecryptActivity::class.java)
|
||||||
putExtra("NAME", intent.getStringExtra("NAME"))
|
startPasswordStoreActivity(intent, noAuth)
|
||||||
putExtra("FILE_PATH", intent.getStringExtra("FILE_PATH"))
|
} else {
|
||||||
putExtra("REPO_PATH", intent.getStringExtra("REPO_PATH"))
|
val intent = Intent(this, PasswordStore::class.java)
|
||||||
putExtra("LAST_CHANGED_TIMESTAMP", intent.getLongExtra("LAST_CHANGED_TIMESTAMP", 0L))
|
val repo = PasswordRepository.initialize()
|
||||||
|
// if repo is null, let PasswordStore handle it.
|
||||||
|
if (repo != null &&
|
||||||
|
!GitSettings.url.isNullOrEmpty() &&
|
||||||
|
sharedPrefs.getBoolean(PreferenceKeys.SYNC_ON_LAUNCH, false)) {
|
||||||
|
binding.progressBar.isVisible = true
|
||||||
|
binding.sync.isVisible = true
|
||||||
|
runGitOperation { startPasswordStoreActivity(intent, noAuth) }
|
||||||
|
} else {
|
||||||
|
startPasswordStoreActivity(intent, noAuth)
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
Intent(this, PasswordStore::class.java)
|
}
|
||||||
startActivity(intentToStart)
|
|
||||||
|
|
||||||
Handler().postDelayed({ finish() }, if (noAuth) 0L else 500L)
|
private fun startPasswordStoreActivity(intent: Intent, noAuth: Boolean) {
|
||||||
|
Handler().postDelayed({
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}, if (noAuth) 500L else 0L)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runGitOperation(onCompletion: () -> Unit) = lifecycleScope.launch {
|
||||||
|
val gitOp = if (GitSettings.authMode == AuthMode.None) GitOp.PULL else GitOp.SYNC
|
||||||
|
launchGitOperation(gitOp).fold(
|
||||||
|
success = { onCompletion.invoke() },
|
||||||
|
failure = { promptOnErrorHandler(it) { onCompletion.invoke() } },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@@ -46,6 +46,7 @@ import com.zeapo.pwdstore.autofill.AutofillPreferenceActivity
|
|||||||
import com.zeapo.pwdstore.crypto.BasePgpActivity
|
import com.zeapo.pwdstore.crypto.BasePgpActivity
|
||||||
import com.zeapo.pwdstore.git.GitConfigActivity
|
import com.zeapo.pwdstore.git.GitConfigActivity
|
||||||
import com.zeapo.pwdstore.git.GitServerConfigActivity
|
import com.zeapo.pwdstore.git.GitServerConfigActivity
|
||||||
|
import com.zeapo.pwdstore.git.config.GitSettings
|
||||||
import com.zeapo.pwdstore.git.sshj.SshKey
|
import com.zeapo.pwdstore.git.sshj.SshKey
|
||||||
import com.zeapo.pwdstore.pwgenxkpwd.XkpwdDictionary
|
import com.zeapo.pwdstore.pwgenxkpwd.XkpwdDictionary
|
||||||
import com.zeapo.pwdstore.sshkeygen.ShowSshKeyFragment
|
import com.zeapo.pwdstore.sshkeygen.ShowSshKeyFragment
|
||||||
@@ -424,6 +425,8 @@ class UserPreference : AppCompatActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findPreference<CheckBoxPreference>(PreferenceKeys.SYNC_ON_LAUNCH)?.isVisible = !GitSettings.url.isNullOrEmpty()
|
||||||
|
|
||||||
val prefCustomXkpwdDictionary = findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT)
|
val prefCustomXkpwdDictionary = findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT)
|
||||||
prefCustomXkpwdDictionary?.onPreferenceClickListener = ClickListener {
|
prefCustomXkpwdDictionary?.onPreferenceClickListener = ClickListener {
|
||||||
prefsActivity.storeCustomDictionaryPath()
|
prefsActivity.storeCustomDictionaryPath()
|
||||||
|
@@ -77,6 +77,7 @@ object PreferenceKeys {
|
|||||||
const val SSH_OPENKEYSTORE_CLEAR_KEY_ID = "ssh_openkeystore_clear_keyid"
|
const val SSH_OPENKEYSTORE_CLEAR_KEY_ID = "ssh_openkeystore_clear_keyid"
|
||||||
const val SSH_OPENKEYSTORE_KEYID = "ssh_openkeystore_keyid"
|
const val SSH_OPENKEYSTORE_KEYID = "ssh_openkeystore_keyid"
|
||||||
const val SSH_SEE_KEY = "ssh_see_key"
|
const val SSH_SEE_KEY = "ssh_see_key"
|
||||||
|
const val SYNC_ON_LAUNCH = "sync_on_launch"
|
||||||
|
|
||||||
@Deprecated("To be used only in Migrations.kt")
|
@Deprecated("To be used only in Migrations.kt")
|
||||||
const val USE_GENERATED_KEY = "use_generated_key"
|
const val USE_GENERATED_KEY = "use_generated_key"
|
||||||
|
59
app/src/main/res/layout/activity_launch.xml
Normal file
59
app/src/main/res/layout/activity_launch.xml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/app_icon"
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:contentDescription="@string/app_icon_hint"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
|
android:transitionName="transition_first_app_icon"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/app_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||||
|
android:textColor="@color/color_control_normal"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:transitionName="transition_first_run_app_name"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/app_icon" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.85" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/sync"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/syncing"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
android:textColor="@color/color_control_normal"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/progress_bar" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -407,6 +407,9 @@
|
|||||||
<!-- SSH port validation -->
|
<!-- SSH port validation -->
|
||||||
<string name="ssh_scheme_needed_title">Potentially incorrect URL</string>
|
<string name="ssh_scheme_needed_title">Potentially incorrect URL</string>
|
||||||
<string name="ssh_scheme_needed_message">It appears that your URL contains a custom port, but does not specify the ssh:// scheme.\nThis can cause the port to be considered a part of your path. Press OK here to fix the URL.</string>
|
<string name="ssh_scheme_needed_message">It appears that your URL contains a custom port, but does not specify the ssh:// scheme.\nThis can cause the port to be considered a part of your path. Press OK here to fix the URL.</string>
|
||||||
|
<string name="sync_on_launch_title">Sync on launch</string>
|
||||||
|
<string name="sync_on_launch_summary">Sync passwords when application is launched</string>
|
||||||
|
<string name="syncing">Syncing…</string>
|
||||||
|
|
||||||
<!-- Proxy configuration activity -->
|
<!-- Proxy configuration activity -->
|
||||||
<string name="proxy_hostname">Proxy hostname</string>
|
<string name="proxy_hostname">Proxy hostname</string>
|
||||||
|
@@ -138,6 +138,12 @@
|
|||||||
app:key="biometric_auth"
|
app:key="biometric_auth"
|
||||||
app:summary="@string/biometric_auth_summary"
|
app:summary="@string/biometric_auth_summary"
|
||||||
app:title="@string/biometric_auth_title" />
|
app:title="@string/biometric_auth_title" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
app:defaultValue="false"
|
||||||
|
app:key="sync_on_launch"
|
||||||
|
app:persistent="true"
|
||||||
|
app:summary="@string/sync_on_launch_summary"
|
||||||
|
app:title="@string/sync_on_launch_title" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory app:title="@string/pref_category_title_passwords">
|
<PreferenceCategory app:title="@string/pref_category_title_passwords">
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
|
Reference in New Issue
Block a user