aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDiogenes Molinares <amolinares19@gmail.com>2020-08-20 13:53:34 +0200
committerGitHub <noreply@github.com>2020-08-20 17:23:34 +0530
commitcfb42f02f5ce7cb9c58e757007e7258e9db0559f (patch)
tree620175e2069ebd335fae273615c0c85c2762fc29 /app
parent152d86ec3a951bd6cb797128094d933d2c3a5697 (diff)
Sort by recently used (#1031)
* Sort passwords by recently used * reformat * modified CHANGELOG.md * restore format CHANGELOG.md * added new sharedPreferences file to manage recent password history * associate timestamp when rename category * associate timestamp when rename password * reformat * Update CHANGELOG.md Co-authored-by: Fabian Henneke <FabianHenneke@users.noreply.github.com> * Update app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt Co-authored-by: Fabian Henneke <FabianHenneke@users.noreply.github.com> * Update app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt Co-authored-by: Fabian Henneke <FabianHenneke@users.noreply.github.com> * use kotlin edit extension * Add changelog entry correctly Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Save paths as Base64 hashes Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Missed it Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> Co-authored-by: Fabian Henneke <FabianHenneke@users.noreply.github.com> Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt12
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt13
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/SearchableRepositoryViewModel.kt1
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt14
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt5
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt13
-rw-r--r--app/src/main/res/values/arrays.xml2
-rw-r--r--app/src/main/res/values/strings.xml1
8 files changed, 61 insertions, 0 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
index 6657afaf..9e50ad2b 100644
--- a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
@@ -16,6 +16,7 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.view.ActionMode
+import androidx.core.content.edit
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.DividerItemDecoration
@@ -32,6 +33,9 @@ import com.zeapo.pwdstore.ui.adapters.PasswordItemRecyclerAdapter
import com.zeapo.pwdstore.ui.dialogs.ItemCreationBottomSheet
import com.zeapo.pwdstore.utils.PasswordItem
import com.zeapo.pwdstore.utils.PasswordRepository
+import com.zeapo.pwdstore.utils.PreferenceKeys
+import com.zeapo.pwdstore.utils.base64
+import com.zeapo.pwdstore.utils.getString
import com.zeapo.pwdstore.utils.sharedPrefs
import com.zeapo.pwdstore.utils.viewBinding
import java.io.File
@@ -243,6 +247,14 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
try {
listener = object : OnFragmentInteractionListener {
override fun onFragmentInteraction(item: PasswordItem) {
+ if (settings.getString(PreferenceKeys.SORT_ORDER) == PasswordRepository.PasswordSortOrder.RECENTLY_USED.name) {
+ //save the time when password was used
+ val preferences = context.getSharedPreferences("recent_password_history", Context.MODE_PRIVATE)
+ preferences.edit {
+ putString(item.file.absolutePath.base64(), System.currentTimeMillis().toString())
+ }
+ }
+
if (item.type == PasswordItem.TYPE_CATEGORY) {
navigateTo(item.file)
} else {
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
index 3ebd35b8..fe1ab085 100644
--- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
@@ -6,6 +6,7 @@ package com.zeapo.pwdstore
import android.Manifest
import android.annotation.SuppressLint
+import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ShortcutInfo.Builder
@@ -63,6 +64,7 @@ import com.zeapo.pwdstore.utils.PasswordRepository.Companion.initialize
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.isInitialized
import com.zeapo.pwdstore.utils.PasswordRepository.PasswordSortOrder.Companion.getSortOrder
import com.zeapo.pwdstore.utils.PreferenceKeys
+import com.zeapo.pwdstore.utils.base64
import com.zeapo.pwdstore.utils.commitChange
import com.zeapo.pwdstore.utils.contains
import com.zeapo.pwdstore.utils.getString
@@ -753,6 +755,17 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {
!newCategory.isInsideRepository() -> renameCategory(oldCategory, CategoryRenameError.DestinationOutsideRepo)
else -> lifecycleScope.launch(Dispatchers.IO) {
moveFile(oldCategory.file, newCategory)
+
+ //associate the new category with the last category's timestamp in history
+ val preference = getSharedPreferences("recent_password_history", Context.MODE_PRIVATE)
+ val timestamp = preference.getString(oldCategory.file.absolutePath)
+ if (timestamp != null) {
+ preference.edit {
+ remove(oldCategory.file.absolutePath.base64())
+ putString(newCategory.absolutePath.base64(), timestamp)
+ }
+ }
+
withContext(Dispatchers.Main) {
commitChange(
resources.getString(R.string.git_commit_move_text, oldCategory.name, newCategory.name),
diff --git a/app/src/main/java/com/zeapo/pwdstore/SearchableRepositoryViewModel.kt b/app/src/main/java/com/zeapo/pwdstore/SearchableRepositoryViewModel.kt
index 7ffa71a3..0509a3dd 100644
--- a/app/src/main/java/com/zeapo/pwdstore/SearchableRepositoryViewModel.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/SearchableRepositoryViewModel.kt
@@ -96,6 +96,7 @@ private fun PasswordItem.Companion.makeComparator(
// declare them all equal at this stage.
PasswordRepository.PasswordSortOrder.INDEPENDENT -> Comparator<PasswordItem> { _, _ -> 0 }
PasswordRepository.PasswordSortOrder.FILE_FIRST -> compareByDescending { it.type }
+ PasswordRepository.PasswordSortOrder.RECENTLY_USED -> PasswordRepository.PasswordSortOrder.RECENTLY_USED.comparator
}
.then(compareBy(nullsLast(CaseInsensitiveComparator)) {
directoryStructure.getIdentifierFor(it.file)
diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt
index 1376dd04..c5d3d70a 100644
--- a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt
@@ -5,6 +5,7 @@
package com.zeapo.pwdstore.crypto
+import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.InputType
@@ -14,6 +15,7 @@ import android.view.View
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult
+import androidx.core.content.edit
import androidx.core.view.isVisible
import androidx.core.widget.doOnTextChanged
import androidx.lifecycle.lifecycleScope
@@ -30,6 +32,7 @@ import com.zeapo.pwdstore.ui.dialogs.PasswordGeneratorDialogFragment
import com.zeapo.pwdstore.ui.dialogs.XkPasswordGeneratorDialogFragment
import com.zeapo.pwdstore.utils.PasswordRepository
import com.zeapo.pwdstore.utils.PreferenceKeys
+import com.zeapo.pwdstore.utils.base64
import com.zeapo.pwdstore.utils.commitChange
import com.zeapo.pwdstore.utils.getString
import com.zeapo.pwdstore.utils.isInsideRepository
@@ -411,6 +414,17 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
return@executeApiAsync
}
+ //associate the new password name with the last name's timestamp in history
+ val preference = getSharedPreferences("recent_password_history", Context.MODE_PRIVATE)
+ val oldFilePathHash = "$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg".base64()
+ val timestamp = preference.getString(oldFilePathHash)
+ if (timestamp != null) {
+ preference.edit {
+ remove(oldFilePathHash)
+ putString(file.absolutePath.base64(), timestamp)
+ }
+ }
+
val returnIntent = Intent()
returnIntent.putExtra(RETURN_EXTRA_CREATED_FILE, path)
returnIntent.putExtra(RETURN_EXTRA_NAME, editName)
diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
index 96bf1b7e..561b8d99 100644
--- a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
@@ -9,6 +9,7 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
+import android.util.Base64
import android.util.TypedValue
import android.view.View
import android.view.autofill.AutofillManager
@@ -42,6 +43,10 @@ fun String.splitLines(): Array<String> {
return split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
}
+fun String.base64(): String {
+ return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP)
+}
+
val Context.clipboard get() = getSystemService<ClipboardManager>()
fun FragmentActivity.snackbar(
diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt
index 8a49f0e3..45453d4f 100644
--- a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt
@@ -4,6 +4,7 @@
*/
package com.zeapo.pwdstore.utils
+import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import com.zeapo.pwdstore.Application
@@ -31,6 +32,18 @@ open class PasswordRepository protected constructor() {
p1.name.compareTo(p2.name, ignoreCase = true)
}),
+ RECENTLY_USED(Comparator { p1: PasswordItem, p2: PasswordItem ->
+ val recentHistory = Application.instance.getSharedPreferences("recent_password_history", Context.MODE_PRIVATE)
+ val timeP1 = recentHistory.getString(p1.file.absolutePath.base64())
+ val timeP2 = recentHistory.getString(p2.file.absolutePath.base64())
+ when {
+ timeP1 != null && timeP2 != null -> timeP2.compareTo(timeP1)
+ timeP1 != null && timeP2 == null -> return@Comparator -1
+ timeP1 == null && timeP2 != null -> return@Comparator 1
+ else -> p1.name.compareTo(p2.name, ignoreCase = true)
+ }
+ }),
+
FILE_FIRST(Comparator { p1: PasswordItem, p2: PasswordItem ->
(p2.type + p1.name).compareTo(p1.type + p2.name, ignoreCase = true)
});
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 6b5edf6c..2b320f31 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -8,11 +8,13 @@
<item>@string/pref_folder_first_sort_order</item>
<item>@string/pref_file_first_sort_order</item>
<item>@string/pref_type_independent_sort_order</item>
+ <item>@string/pref_recently_used_sort_order</item>
</string-array>
<string-array name="sort_order_values">
<item>FOLDER_FIRST</item>
<item>FILE_FIRST</item>
<item>INDEPENDENT</item>
+ <item>RECENTLY_USED</item>
</string-array>
<string-array name="capitalization_type_values">
<item>lowercase</item>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fe2a3488..ff1d5238 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -140,6 +140,7 @@
<string name="pref_folder_first_sort_order">Folders first</string>
<string name="pref_file_first_sort_order">Files first</string>
<string name="pref_type_independent_sort_order">Type independent</string>
+ <string name="pref_recently_used_sort_order">Recently used</string>
<string name="pref_autofill_title">Autofill</string>
<string name="pref_autofill_enable_title">Enable Autofill</string>
<string name="pref_autofill_enable_msg">Tap OK to go to Accessibility settings. There, tap Password Store under Services then tap the switch in the top right to turn it on or off.</string>