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:
Gigahawk 2020-02-19 22:19:09 -08:00 committed by GitHub
parent bcdc43b1f1
commit 9255583f2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 5 deletions

View file

@ -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

View file

@ -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)

View file

@ -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)
} }

View file

@ -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> {

View file

@ -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"-->

View file

@ -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>

View file

@ -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"