mirror of
https://github.com/yogeshpaliyal/KeyPass.git
synced 2026-01-04 16:47:32 -06:00
New Feature -> Auto backup whenever there is changes in accounts :D
Added Chinese (Simplified)
This commit is contained in:
@@ -20,8 +20,8 @@ android {
|
||||
applicationId appPackageId
|
||||
minSdkVersion 22
|
||||
targetSdkVersion 30
|
||||
versionCode 1308
|
||||
versionName "1.3.8"
|
||||
versionCode 1309
|
||||
versionName "1.3.9"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -79,7 +79,7 @@ dependencies {
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
@@ -112,15 +112,23 @@ dependencies {
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:2.6.0"
|
||||
|
||||
|
||||
|
||||
|
||||
//Androidx Security
|
||||
implementation "androidx.security:security-crypto:1.1.0-alpha03"
|
||||
|
||||
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'com.google.code.gson:gson:2.8.8'
|
||||
|
||||
|
||||
// dependency injection
|
||||
implementation("com.google.dagger:hilt-android:$hilt_version")
|
||||
kapt("com.google.dagger:hilt-android-compiler:$hilt_version")
|
||||
implementation("androidx.hilt:hilt-work:1.0.0")
|
||||
// When using Kotlin.
|
||||
kapt("androidx.hilt:hilt-compiler:1.0.0")
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.yogeshpaliyal.keypass">
|
||||
|
||||
<application
|
||||
@@ -10,8 +11,7 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.KeyPass">
|
||||
<activity
|
||||
android:name=".ui.backup.BackupActivity"/>
|
||||
<activity android:name=".ui.backup.BackupActivity" />
|
||||
<activity android:name=".ui.generate.GeneratePasswordActivity" />
|
||||
<activity android:name=".ui.auth.AuthenticationActivity">
|
||||
<intent-filter>
|
||||
@@ -34,6 +34,15 @@
|
||||
<meta-data
|
||||
android:name="preloaded_fonts"
|
||||
android:resource="@array/preloaded_fonts" />
|
||||
|
||||
|
||||
<!-- If you want to disable android.startup completely. -->
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
tools:node="remove">
|
||||
</provider>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.yogeshpaliyal.keypass
|
||||
|
||||
import android.app.Application
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.work.Configuration
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import javax.inject.Inject
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
@@ -10,14 +13,25 @@ import dagger.hilt.android.HiltAndroidApp
|
||||
* created on 22-01-2021 22:41
|
||||
*/
|
||||
@HiltAndroidApp
|
||||
class MyApplication : Application() {
|
||||
class MyApplication : Application(), Configuration.Provider {
|
||||
|
||||
companion object {
|
||||
lateinit var instance: MyApplication
|
||||
}
|
||||
@Inject
|
||||
lateinit var workerFactory: HiltWorkerFactory
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this
|
||||
}
|
||||
|
||||
override fun getWorkManagerConfiguration(): Configuration {
|
||||
return Configuration.Builder()
|
||||
.setMinimumLoggingLevel(android.util.Log.INFO)
|
||||
.setWorkerFactory(workerFactory)
|
||||
.build()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package com.yogeshpaliyal.keypass.db
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.*
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@@ -41,4 +38,7 @@ abstract class DbDao {
|
||||
|
||||
@Query("DELETE from account WHERE id = :id")
|
||||
abstract fun deleteAccount(id: Long?)
|
||||
|
||||
@Delete
|
||||
abstract fun deleteAccount(accountModel: AccountModel)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceCategory
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
@@ -80,6 +81,7 @@ class BackupActivity : AppCompatActivity() {
|
||||
if (it.canUserAccessBackupDirectory(sp)) {
|
||||
val selectedDirectory = Uri.parse(getBackupDirectory(sp))
|
||||
backup(selectedDirectory)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,20 +100,60 @@ class BackupActivity : AppCompatActivity() {
|
||||
}
|
||||
updateItems()
|
||||
}
|
||||
getString(R.string.settings_override_auto_backup) -> {
|
||||
sp.apply {
|
||||
setOverrideAutoBackup(overrideAutoBackup().not())
|
||||
}
|
||||
updateItems()
|
||||
}
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
|
||||
fun backup(selectedDirectory: Uri){
|
||||
lifecycleScope.launch {
|
||||
context.backupAccounts(sp, appDb,selectedDirectory)?.let { keyPair ->
|
||||
if (keyPair.first) {
|
||||
val binding = LayoutBackupKeypharseBinding.inflate(layoutInflater)
|
||||
binding.txtCode.text = getOrCreateBackupKey(sp).second
|
||||
binding.txtCode.setOnClickListener {
|
||||
val clipboard =
|
||||
ContextCompat.getSystemService(
|
||||
requireContext(),
|
||||
ClipboardManager::class.java
|
||||
)
|
||||
val clip = ClipData.newPlainText("KeyPass", binding.txtCode.text)
|
||||
clipboard?.setPrimaryClip(clip)
|
||||
Toast.makeText(context, getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
MaterialAlertDialogBuilder(requireContext()).setView(binding.root)
|
||||
.setPositiveButton(
|
||||
getString(R.string.yes)
|
||||
) { dialog, which ->
|
||||
dialog?.dismiss()
|
||||
}.show()
|
||||
} else {
|
||||
Toast.makeText(context, getString(R.string.backup_completed), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
updateItems()
|
||||
}
|
||||
|
||||
private fun updateItems() {
|
||||
val isBackupEnabled = context.canUserAccessBackupDirectory(sp)
|
||||
|
||||
val isAutoBackupEnabled = sp.isAutoBackupEnabled()
|
||||
|
||||
findPreference<Preference>(getString(R.string.settings_start_backup))?.isVisible = isBackupEnabled.not()
|
||||
findPreference<Preference>(getString(R.string.settings_stop_backup))?.isVisible = isBackupEnabled
|
||||
|
||||
findPreference<Preference>(getString(R.string.settings_auto_backup))?.isVisible = isBackupEnabled
|
||||
findPreference<Preference>(getString(R.string.settings_auto_backup))?.summary = if(isAutoBackupEnabled) getString(R.string.enabled) else getString(R.string.disabled)
|
||||
|
||||
findPreference<PreferenceCategory>(getString(R.string.settings_cat_auto_backup))?.isVisible = isBackupEnabled && isAutoBackupEnabled
|
||||
|
||||
findPreference<Preference>(getString(R.string.settings_override_auto_backup))?.summary = if(sp.overrideAutoBackup()) getString(R.string.enabled) else getString(R.string.disabled)
|
||||
|
||||
findPreference<Preference>(getString(R.string.settings_create_backup))?.isVisible = isBackupEnabled
|
||||
findPreference<Preference>(getString(R.string.settings_create_backup))?.summary = getString(R.string.last_backup_date, getBackupTime(sp).formatCalendar("dd MMM yyyy hh:mm aa"))
|
||||
@@ -156,50 +198,7 @@ class BackupActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun backup(selectedDirectory: Uri) {
|
||||
|
||||
val keyPair = getOrCreateBackupKey(sp)
|
||||
|
||||
val tempFile = DocumentFile.fromTreeUri(requireContext(), selectedDirectory)?.createFile(
|
||||
"*/*",
|
||||
"key_pass_backup_${System.currentTimeMillis()}.keypass"
|
||||
)
|
||||
|
||||
lifecycleScope.launch {
|
||||
context?.contentResolver?.let {
|
||||
appDb.createBackup(
|
||||
keyPair.second,
|
||||
it,
|
||||
tempFile?.uri
|
||||
)
|
||||
setBackupTime(sp, System.currentTimeMillis())
|
||||
if (keyPair.first) {
|
||||
val binding = LayoutBackupKeypharseBinding.inflate(layoutInflater)
|
||||
binding.txtCode.text = getOrCreateBackupKey(sp).second
|
||||
binding.txtCode.setOnClickListener {
|
||||
val clipboard =
|
||||
ContextCompat.getSystemService(
|
||||
requireContext(),
|
||||
ClipboardManager::class.java
|
||||
)
|
||||
val clip = ClipData.newPlainText("KeyPass", binding.txtCode.text)
|
||||
clipboard?.setPrimaryClip(clip)
|
||||
Toast.makeText(context, getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
MaterialAlertDialogBuilder(requireContext()).setView(binding.root)
|
||||
.setPositiveButton(
|
||||
getString(R.string.yes)
|
||||
) { dialog, which ->
|
||||
dialog?.dismiss()
|
||||
}.show()
|
||||
} else {
|
||||
Toast.makeText(context, getString(R.string.backup_completed), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
updateItems()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeBackupFolder() {
|
||||
startBackup()
|
||||
@@ -213,6 +212,10 @@ class BackupActivity : AppCompatActivity() {
|
||||
clearBackupKey(sp)
|
||||
setBackupDirectory(sp, "")
|
||||
setBackupTime(sp, -1)
|
||||
sp.apply {
|
||||
setOverrideAutoBackup(false)
|
||||
setAutoBackupEnabled(false)
|
||||
}
|
||||
updateItems()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,11 @@ import android.view.Menu
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.R
|
||||
import com.yogeshpaliyal.keypass.databinding.FragmentDetailBinding
|
||||
import com.yogeshpaliyal.keypass.utils.PasswordGenerator
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
@@ -30,9 +24,6 @@ class DetailActivity : AppCompatActivity() {
|
||||
|
||||
lateinit var binding: FragmentDetailBinding
|
||||
|
||||
@Inject
|
||||
lateinit var appDb: AppDatabase
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ARG_ACCOUNT_ID = "ARG_ACCOUNT_ID"
|
||||
@@ -90,14 +81,8 @@ class DetailActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
binding.btnSave.setOnClickListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val model = mViewModel.accountModel.value
|
||||
if (model != null) {
|
||||
appDb.getDao().insertOrUpdateAccount(model)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
onBackPressed()
|
||||
}
|
||||
mViewModel.insertOrUpdate {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,11 +95,9 @@ class DetailActivity : AppCompatActivity() {
|
||||
getString(R.string.delete)
|
||||
) { dialog, which ->
|
||||
dialog?.dismiss()
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
if (accountId > 0L) {
|
||||
appDb.getDao().deleteAccount(accountId)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
|
||||
if (accountId > 0L) {
|
||||
mViewModel.deleteAccount {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package com.yogeshpaliyal.keypass.ui.detail
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import com.yogeshpaliyal.keypass.worker.executeAutoBackup
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/*
|
||||
@@ -18,16 +22,44 @@ import javax.inject.Inject
|
||||
* created on 31-01-2021 11:52
|
||||
*/
|
||||
@HiltViewModel
|
||||
class DetailViewModel @Inject constructor(application: Application, val appDb: AppDatabase) : AndroidViewModel(application) {
|
||||
class DetailViewModel @Inject constructor(val app: Application, val appDb: AppDatabase,val sp: SharedPreferences) : AndroidViewModel(app) {
|
||||
|
||||
val accountModel by lazy { MutableLiveData<AccountModel>() }
|
||||
private val _accountModel by lazy { MutableLiveData<AccountModel>() }
|
||||
val accountModel : LiveData<AccountModel> = _accountModel
|
||||
|
||||
fun loadAccount(accountId: Long?) {
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountModel.postValue(
|
||||
_accountModel.postValue(
|
||||
appDb.getDao().getAccount(accountId) ?: AccountModel()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteAccount(onExecCompleted : ()->Unit){
|
||||
viewModelScope.launch {
|
||||
accountModel.value?.let {
|
||||
withContext(Dispatchers.IO) {
|
||||
appDb.getDao().deleteAccount(it)
|
||||
}
|
||||
autoBackup()
|
||||
onExecCompleted()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun insertOrUpdate(onExecCompleted : ()->Unit){
|
||||
viewModelScope.launch {
|
||||
accountModel.value?.let {
|
||||
withContext(Dispatchers.IO) {
|
||||
appDb.getDao().insertOrUpdateAccount(it)
|
||||
autoBackup()
|
||||
}
|
||||
}
|
||||
onExecCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
private fun autoBackup(){
|
||||
app.executeAutoBackup(sp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.db_helper.createBackup
|
||||
import java.security.SecureRandom
|
||||
|
||||
/*
|
||||
@@ -21,9 +23,9 @@ fun getRandomString(sizeOfRandomString: Int): String {
|
||||
val sb = StringBuilder(sizeOfRandomString)
|
||||
for (i in 0 until sizeOfRandomString) sb.append(
|
||||
ALLOWED_CHARACTERS[
|
||||
random.nextInt(
|
||||
ALLOWED_CHARACTERS.length
|
||||
)
|
||||
random.nextInt(
|
||||
ALLOWED_CHARACTERS.length
|
||||
)
|
||||
]
|
||||
)
|
||||
return sb.toString()
|
||||
@@ -36,6 +38,42 @@ fun Context?.canUserAccessBackupDirectory(sp: SharedPreferences): Boolean {
|
||||
return backupDirectory != null && backupDirectory.exists() && backupDirectory.canRead() && backupDirectory.canWrite()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Pair (Boolean to check if backup is for first time, is backup is for first time show user alert to save encryption key)
|
||||
* Second Value contains the encryption key
|
||||
*/
|
||||
suspend fun Context?.backupAccounts(
|
||||
sp: SharedPreferences,
|
||||
appDb: AppDatabase,
|
||||
selectedDirectory: Uri, fileName: String? = null
|
||||
): Pair<Boolean, String>? {
|
||||
|
||||
this ?: return null
|
||||
|
||||
val keyPair = getOrCreateBackupKey(sp)
|
||||
|
||||
val fileName = (fileName ?: "key_pass_backup_${System.currentTimeMillis()}")+".keypass"
|
||||
|
||||
|
||||
val directory = DocumentFile.fromTreeUri(this, selectedDirectory)
|
||||
var docFile = directory?.findFile(fileName)
|
||||
if (docFile == null)
|
||||
docFile = DocumentFile.fromTreeUri(this, selectedDirectory)?.createFile(
|
||||
"*/*",
|
||||
fileName)
|
||||
|
||||
|
||||
val response = appDb.createBackup(
|
||||
keyPair.second,
|
||||
contentResolver,
|
||||
docFile?.uri
|
||||
)
|
||||
setBackupTime(sp, System.currentTimeMillis())
|
||||
|
||||
return keyPair
|
||||
}
|
||||
|
||||
private fun getUri(string: String?): Uri? {
|
||||
val uri = string
|
||||
return if (TextUtils.isEmpty(uri)) {
|
||||
|
||||
@@ -55,6 +55,16 @@ fun SharedPreferences?.isAutoBackupEnabled(): Boolean {
|
||||
return this?.getBoolean(AUTO_BACKUP, false) ?: false
|
||||
}
|
||||
|
||||
fun SharedPreferences?.overrideAutoBackup(): Boolean {
|
||||
return this?.getBoolean(OVERRIDE_AUTO_BACKUP, false) ?: false
|
||||
}
|
||||
|
||||
fun SharedPreferences?.setOverrideAutoBackup(value: Boolean) {
|
||||
this?.edit {
|
||||
putBoolean(OVERRIDE_AUTO_BACKUP, value)
|
||||
}
|
||||
}
|
||||
|
||||
fun SharedPreferences?.setAutoBackupEnabled(value: Boolean) {
|
||||
this?.edit {
|
||||
putBoolean(AUTO_BACKUP, value)
|
||||
@@ -69,3 +79,4 @@ private const val BACKUP_KEY = "backup_key"
|
||||
private const val BACKUP_DIRECTORY = "backup_directory"
|
||||
private const val BACKUP_DATE_TIME = "backup_date_time"
|
||||
private const val AUTO_BACKUP = "auto_backup"
|
||||
private const val OVERRIDE_AUTO_BACKUP = "override_auto_backup"
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.yogeshpaliyal.keypass.worker
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import androidx.hilt.work.HiltWorker
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.utils.backupAccounts
|
||||
import com.yogeshpaliyal.keypass.utils.canUserAccessBackupDirectory
|
||||
import com.yogeshpaliyal.keypass.utils.getBackupDirectory
|
||||
import com.yogeshpaliyal.keypass.utils.overrideAutoBackup
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@HiltWorker
|
||||
class AutoBackupWorker @AssistedInject constructor(
|
||||
@Assisted val appContext: Context, @Assisted params: WorkerParameters,
|
||||
val appDatabase: AppDatabase,
|
||||
val sp: SharedPreferences
|
||||
) :
|
||||
CoroutineWorker(appContext, params) {
|
||||
override suspend fun doWork(): Result {
|
||||
return withContext(Dispatchers.IO) {
|
||||
|
||||
if (appContext.canUserAccessBackupDirectory(sp)) {
|
||||
val selectedDirectory = Uri.parse(getBackupDirectory(sp))
|
||||
appContext.backupAccounts(
|
||||
sp,
|
||||
appDatabase,
|
||||
selectedDirectory,
|
||||
if (sp.overrideAutoBackup()) "key_pass_auto_backup" else null
|
||||
)
|
||||
}
|
||||
|
||||
Result.success()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.yogeshpaliyal.keypass.worker
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.yogeshpaliyal.keypass.utils.isAutoBackupEnabled
|
||||
|
||||
fun Context?.executeAutoBackup(sp: SharedPreferences){
|
||||
this ?: return
|
||||
|
||||
if (sp.isAutoBackupEnabled()) {
|
||||
val work = OneTimeWorkRequestBuilder<AutoBackupWorker>().build()
|
||||
|
||||
WorkManager.getInstance(this.applicationContext)
|
||||
.enqueueUniqueWork("AutoBackupWorker", ExistingWorkPolicy.KEEP, work)
|
||||
}
|
||||
}
|
||||
@@ -59,4 +59,9 @@
|
||||
<string name="tags_comma_separated_optional">टैग अल्पविराम से अलग (वैकल्पिक)</string>
|
||||
<string name="website_url_optional">वेबसाइट यूआरएल (वैकल्पिक)</string>
|
||||
<string name="notes_optional">नोट्स (वैकल्पिक)</string>
|
||||
|
||||
<string name="auto_backup">ऑटो बैकअप</string>
|
||||
<string name="disabled">अक्षम</string>
|
||||
<string name="enabled">सक्रिय</string>
|
||||
<string name="override_auto_backup_file">ऑटो बैकअप फ़ाइल को ओवरराइड करें</string>
|
||||
</resources>
|
||||
@@ -59,4 +59,9 @@
|
||||
<string name="tags_comma_separated_optional">标签(选填)</string>
|
||||
<string name="website_url_optional">网站(选填)</string>
|
||||
<string name="notes_optional">附注(选填)</string>
|
||||
|
||||
<string name="auto_backup">自动备份</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="enabled">启用</string>
|
||||
<string name="override_auto_backup_file">覆盖自动备份文件</string>
|
||||
</resources>
|
||||
@@ -62,4 +62,5 @@
|
||||
<string name="auto_backup">Auto Backup</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="override_auto_backup_file">Override Auto Backup File</string>
|
||||
</resources>
|
||||
@@ -10,5 +10,7 @@
|
||||
<string name="settings_backup_folder" translatable="false">backup_folder</string>
|
||||
<string name="settings_stop_backup" translatable="false">stop_backup</string>
|
||||
<string name="settings_auto_backup" translatable="false">auto_backup</string>
|
||||
<string name="settings_cat_auto_backup" translatable="false">cat_auto_backup</string>
|
||||
<string name="settings_override_auto_backup" translatable="false">override_auto_backup</string>
|
||||
|
||||
</resources>
|
||||
@@ -3,39 +3,52 @@
|
||||
|
||||
<PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
app:summary="@string/backup_desc"/>
|
||||
<Preference app:summary="@string/backup_desc" />
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_start_backup"
|
||||
app:title="@string/turn_on_backup"/>
|
||||
app:title="@string/turn_on_backup" />
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_create_backup"
|
||||
app:title="@string/create_backup"
|
||||
tools:summary="Last backup : 7m"/>
|
||||
tools:summary="Last backup : 7m" />
|
||||
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_backup_folder"
|
||||
app:title="@string/backup_folder"
|
||||
tools:summary="@string/backup"/>
|
||||
tools:summary="@string/backup" />
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_auto_backup"
|
||||
app:title="@string/auto_backup"
|
||||
tools:summary="@string/disabled"/>
|
||||
tools:summary="@string/disabled" />
|
||||
|
||||
<PreferenceCategory
|
||||
app:key="@string/settings_cat_auto_backup"
|
||||
app:title="@string/auto_backup"
|
||||
app:allowDividerBelow="true">
|
||||
|
||||
<Preference app:summary="Your accounts will be backed up whenever account is added or modified" />
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_override_auto_backup"
|
||||
app:title="@string/override_auto_backup_file"
|
||||
tools:summary="@string/disabled" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_verify_key_phrase"
|
||||
app:title="@string/verify_keyphrase"
|
||||
app:summary="@string/verify_keyphrase_message"/>
|
||||
app:summary="@string/verify_keyphrase_message"
|
||||
app:title="@string/verify_keyphrase" />
|
||||
|
||||
|
||||
<Preference
|
||||
app:key="@string/settings_stop_backup"
|
||||
app:isPreferenceVisible="false"
|
||||
app:title="@string/turn_off_backup"/>
|
||||
app:key="@string/settings_stop_backup"
|
||||
app:title="@string/turn_off_backup" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
1
fastlane/metadata/android/en-US/changelogs/1308.txt
Normal file
1
fastlane/metadata/android/en-US/changelogs/1308.txt
Normal file
@@ -0,0 +1 @@
|
||||
Fixed crash for some devices when creating backup
|
||||
2
fastlane/metadata/android/en-US/changelogs/1309.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/1309.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
New Feature -> Auto backup whenever there is changes in accounts :D
|
||||
Added Chinese (Simplified)
|
||||
@@ -1 +1,2 @@
|
||||
Fixed crash for some devices when creating backup
|
||||
New Feature -> Auto backup whenever there is changes in accounts :D
|
||||
Added Chinese (Simplified)
|
||||
Reference in New Issue
Block a user