Better UI flow (#630)
* Filter against entire pathname when searching * Add option to directly open search dialog on start * Replace basic search filter with fuzzy search * Update CHANGELOG Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Open search in onResume, force search icon to always show * Add option to always search from root directory Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
parent
bcdc43b1f1
commit
9255583f2d
7 changed files with 55 additions and 5 deletions
|
@ -6,9 +6,12 @@ All notable changes to this project will be documented in this file.
|
||||||
### Added
|
### Added
|
||||||
- Fast scroller with alphabetic hints
|
- Fast scroller with alphabetic hints
|
||||||
- UI button to create new folders
|
- UI button to create new folders
|
||||||
|
- Option to directly start searching when opening the app
|
||||||
|
- Option to always search from root folder regardless of the currently open folder
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Logging is now enabled in release builds
|
- Logging is now enabled in release builds
|
||||||
|
- Searching now shows folders as well as the passwords inside them
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- OpenKeychain errors cause app crash
|
- OpenKeychain errors cause app crash
|
||||||
|
|
|
@ -24,7 +24,6 @@ import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getPasswords
|
||||||
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory
|
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory
|
||||||
import com.zeapo.pwdstore.utils.PasswordRepository.PasswordSortOrder.Companion.getSortOrder
|
import com.zeapo.pwdstore.utils.PasswordRepository.PasswordSortOrder.Companion.getSortOrder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Locale
|
|
||||||
import java.util.Stack
|
import java.util.Stack
|
||||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||||
|
|
||||||
|
@ -157,10 +156,36 @@ class PasswordFragment : Fragment() {
|
||||||
if (filter.isEmpty()) {
|
if (filter.isEmpty()) {
|
||||||
refreshAdapter()
|
refreshAdapter()
|
||||||
} else {
|
} else {
|
||||||
recursiveFilter(filter, if (pathStack.isEmpty()) null else pathStack.peek())
|
recursiveFilter(
|
||||||
|
filter,
|
||||||
|
if (pathStack.isEmpty() ||
|
||||||
|
settings.getBoolean("search_from_root", false))
|
||||||
|
null
|
||||||
|
else pathStack.peek())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fuzzy matches the filter against the given string
|
||||||
|
*
|
||||||
|
* based on https://www.forrestthewoods.com/blog/reverse_engineering_sublime_texts_fuzzy_match/
|
||||||
|
*
|
||||||
|
* @param filter the filter to apply
|
||||||
|
* @param str the string to filter against
|
||||||
|
*
|
||||||
|
* @return true if the filter fuzzymatches the string
|
||||||
|
*/
|
||||||
|
private fun fuzzyMatch(filter: String, str: String): Boolean {
|
||||||
|
var i = 0
|
||||||
|
var j = 0
|
||||||
|
while (i < filter.length && j < str.length) {
|
||||||
|
if (filter[i].isWhitespace() || filter[i].toLowerCase() == str[j].toLowerCase())
|
||||||
|
i++
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
return i == filter.length
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* recursively filters a directory and extract all the matching items
|
* recursively filters a directory and extract all the matching items
|
||||||
*
|
*
|
||||||
|
@ -177,7 +202,7 @@ class PasswordFragment : Fragment() {
|
||||||
if (item.type == PasswordItem.TYPE_CATEGORY && rec) {
|
if (item.type == PasswordItem.TYPE_CATEGORY && rec) {
|
||||||
recursiveFilter(filter, item.file)
|
recursiveFilter(filter, item.file)
|
||||||
}
|
}
|
||||||
val matches = item.toString().toLowerCase(Locale.ROOT).contains(filter.toLowerCase(Locale.ROOT))
|
val matches = fuzzyMatch(filter, item.longName)
|
||||||
val inAdapter = recyclerAdapter.values.contains(item)
|
val inAdapter = recyclerAdapter.values.contains(item)
|
||||||
if (matches && !inAdapter) {
|
if (matches && !inAdapter) {
|
||||||
recyclerAdapter.add(item)
|
recyclerAdapter.add(item)
|
||||||
|
|
|
@ -142,6 +142,11 @@ class PasswordStore : AppCompatActivity() {
|
||||||
} else {
|
} else {
|
||||||
checkLocalRepository()
|
checkLocalRepository()
|
||||||
}
|
}
|
||||||
|
if (settings.getBoolean("search_on_start", false) && ::searchItem.isInitialized) {
|
||||||
|
if (!searchItem.isActionViewExpanded) {
|
||||||
|
searchItem.expandActionView()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||||
|
@ -183,6 +188,9 @@ class PasswordStore : AppCompatActivity() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (settings.getBoolean("search_on_start", false)) {
|
||||||
|
searchItem.expandActionView()
|
||||||
|
}
|
||||||
return super.onCreateOptionsMenu(menu)
|
return super.onCreateOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ open class PasswordRepository protected constructor() {
|
||||||
/**
|
/**
|
||||||
* Gets the password items in the root directory
|
* Gets the password items in the root directory
|
||||||
*
|
*
|
||||||
* @return a list of passwords in the root direcotyr
|
* @return a list of passwords in the root directory
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getPasswords(rootDir: File, sortOrder: PasswordSortOrder): ArrayList<PasswordItem> {
|
fun getPasswords(rootDir: File, sortOrder: PasswordSortOrder): ArrayList<PasswordItem> {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<item android:id="@+id/action_search"
|
<item android:id="@+id/action_search"
|
||||||
android:title="@string/action_search"
|
android:title="@string/action_search"
|
||||||
android:icon="@drawable/ic_search_white_24dp"
|
android:icon="@drawable/ic_search_white_24dp"
|
||||||
pwstore:showAsAction="ifRoom|collapseActionView"
|
pwstore:showAsAction="always|collapseActionView"
|
||||||
pwstore:actionViewClass="androidx.appcompat.widget.SearchView" />
|
pwstore:actionViewClass="androidx.appcompat.widget.SearchView" />
|
||||||
|
|
||||||
<!--<item android:id="@+id/menu_add_category"-->
|
<!--<item android:id="@+id/menu_add_category"-->
|
||||||
|
|
|
@ -281,4 +281,8 @@
|
||||||
<string name="pref_show_hidden_summary">Include hidden directories in the password list</string>
|
<string name="pref_show_hidden_summary">Include hidden directories in the password list</string>
|
||||||
<string name="title_create_folder">Create folder</string>
|
<string name="title_create_folder">Create folder</string>
|
||||||
<string name="button_create">Create</string>
|
<string name="button_create">Create</string>
|
||||||
|
<string name="pref_search_on_start">Open search on start</string>
|
||||||
|
<string name="pref_search_on_start_hint">Open search bar when app is launched</string>
|
||||||
|
<string name="pref_search_from_root">Always search from root</string>
|
||||||
|
<string name="pref_search_from_root_hint">Search from root of store regardless of currently open directory</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -82,6 +82,16 @@
|
||||||
android:key="filter_recursively"
|
android:key="filter_recursively"
|
||||||
android:summary="@string/pref_recursive_filter_hint"
|
android:summary="@string/pref_recursive_filter_hint"
|
||||||
android:title="@string/pref_recursive_filter" />
|
android:title="@string/pref_recursive_filter" />
|
||||||
|
<androidx.preference.CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="search_on_start"
|
||||||
|
android:summary="@string/pref_search_on_start_hint"
|
||||||
|
android:title="@string/pref_search_on_start" />
|
||||||
|
<androidx.preference.CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="search_from_root"
|
||||||
|
android:summary="@string/pref_search_from_root_hint"
|
||||||
|
android:title="@string/pref_search_from_root" />
|
||||||
<androidx.preference.ListPreference
|
<androidx.preference.ListPreference
|
||||||
android:title="@string/pref_sort_order_title"
|
android:title="@string/pref_sort_order_title"
|
||||||
android:defaultValue="FOLDER_FIRST"
|
android:defaultValue="FOLDER_FIRST"
|
||||||
|
|
Loading…
Reference in a new issue