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>
This commit is contained in:
parent
152d86ec3a
commit
cfb42f02f5
9 changed files with 65 additions and 0 deletions
|
@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Allow sorting by recently used
|
||||
|
||||
## [1.11.0] - 2020-08-18
|
||||
|
||||
### Added
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue