aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt120
-rw-r--r--app/src/main/res/layout/activity_oreo_autofill_filter.xml19
-rw-r--r--app/src/main/res/values/strings.xml1
3 files changed, 80 insertions, 60 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
index 0901f8d9..57a1f21a 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
@@ -111,78 +111,82 @@ class AutofillFilterView : AppCompatActivity() {
supportActionBar?.hide()
bindUI()
+ updateSearch()
setResult(RESULT_CANCELED)
}
private fun bindUI() {
- val recyclerAdapter = SearchableRepositoryAdapter(
- R.layout.oreo_autofill_filter_row,
- ::PasswordViewHolder) { item ->
- val file = item.file.relativeTo(item.rootDir)
- val pathToIdentifier = directoryStructure.getPathToIdentifierFor(file)
- val identifier = directoryStructure.getIdentifierFor(file)
- val accountPart = directoryStructure.getAccountPartFor(file)
- check(identifier != null || accountPart != null) { "At least one of identifier and accountPart should always be non-null" }
- title.text = if (identifier != null) {
- buildSpannedString {
- if (pathToIdentifier != null)
- append("$pathToIdentifier/")
- bold { underline { append(identifier) } }
+ with(binding) {
+ rvPassword.apply {
+ adapter = SearchableRepositoryAdapter(
+ R.layout.oreo_autofill_filter_row,
+ ::PasswordViewHolder
+ ) { item ->
+ val file = item.file.relativeTo(item.rootDir)
+ val pathToIdentifier = directoryStructure.getPathToIdentifierFor(file)
+ val identifier = directoryStructure.getIdentifierFor(file)
+ val accountPart = directoryStructure.getAccountPartFor(file)
+ check(identifier != null || accountPart != null) { "At least one of identifier and accountPart should always be non-null" }
+ title.text = if (identifier != null) {
+ buildSpannedString {
+ if (pathToIdentifier != null)
+ append("$pathToIdentifier/")
+ bold { underline { append(identifier) } }
+ }
+ } else {
+ accountPart
+ }
+ subtitle.apply {
+ if (identifier != null && accountPart != null) {
+ text = accountPart
+ visibility = View.VISIBLE
+ } else {
+ visibility = View.GONE
+ }
+ }
+ }.onItemClicked { _, item ->
+ decryptAndFill(item)
}
- } else {
- accountPart
+ layoutManager = LinearLayoutManager(context)
}
- subtitle.apply {
- if (identifier != null && accountPart != null) {
- text = accountPart
- visibility = View.VISIBLE
- } else {
- visibility = View.GONE
+ search.apply {
+ val initialSearch =
+ formOrigin.getPrettyIdentifier(applicationContext, untrusted = false)
+ setText(initialSearch, TextView.BufferType.EDITABLE)
+ addTextChangedListener { updateSearch() }
+ }
+ strictDomainSearch.apply {
+ visibility = if (formOrigin is FormOrigin.Web) View.VISIBLE else View.GONE
+ isChecked = formOrigin is FormOrigin.Web
+ setOnCheckedChangeListener { _, _ -> updateSearch() }
+ }
+ shouldMatch.text = getString(
+ R.string.oreo_autofill_match_with,
+ formOrigin.getPrettyIdentifier(applicationContext)
+ )
+ model.searchResult.observe(this@AutofillFilterView) { result ->
+ val list = result.passwordItems
+ (rvPassword.adapter as SearchableRepositoryAdapter).submitList(list) {
+ rvPassword.scrollToPosition(0)
+ }
+ // Switch RecyclerView out for a "no results" message if the new list is empty and
+ // the message is not yet shown (and vice versa).
+ if ((list.isEmpty() && rvPasswordSwitcher.nextView.id == rvPasswordEmpty.id) ||
+ (list.isNotEmpty() && rvPasswordSwitcher.nextView.id == rvPassword.id)
+ ) {
+ rvPasswordSwitcher.showNext()
}
}
- }.onItemClicked { _, item ->
- decryptAndFill(item)
- }
- binding.rvPassword.apply {
- adapter = recyclerAdapter
- layoutManager = LinearLayoutManager(context)
}
+ }
- val initialFilter = formOrigin.getPrettyIdentifier(applicationContext, untrusted = false)
- binding.search.setText(initialFilter, TextView.BufferType.EDITABLE)
- val filterMode =
- if (formOrigin is FormOrigin.Web) FilterMode.StrictDomain else FilterMode.Fuzzy
+ private fun updateSearch() {
model.search(
- initialFilter,
- filterMode = filterMode,
+ binding.search.text.toString().trim(),
+ filterMode = if (binding.strictDomainSearch.isChecked) FilterMode.StrictDomain else FilterMode.Fuzzy,
searchMode = SearchMode.RecursivelyInSubdirectories,
listMode = ListMode.FilesOnly
)
- binding.search.addTextChangedListener {
- model.search(
- it.toString().trim(),
- filterMode = FilterMode.Fuzzy,
- searchMode = SearchMode.RecursivelyInSubdirectories,
- listMode = ListMode.FilesOnly
- )
- }
- model.searchResult.observe(this) { result ->
- val list = result.passwordItems
- recyclerAdapter.submitList(list) {
- binding.rvPassword.scrollToPosition(0)
- }
- // Switch RecyclerView out for a "no results" message if the new list is empty and
- // the message is not yet shown (and vice versa).
- if ((list.isEmpty() && binding.rvPasswordSwitcher.nextView.id == binding.rvPasswordEmpty.id) ||
- (list.isNotEmpty() && binding.rvPasswordSwitcher.nextView.id == binding.rvPassword.id)
- )
- binding.rvPasswordSwitcher.showNext()
- }
-
- binding.shouldMatch.text = getString(
- R.string.oreo_autofill_match_with,
- formOrigin.getPrettyIdentifier(applicationContext)
- )
}
private fun decryptAndFill(item: PasswordItem) {
diff --git a/app/src/main/res/layout/activity_oreo_autofill_filter.xml b/app/src/main/res/layout/activity_oreo_autofill_filter.xml
index 7c8740c3..da965e05 100644
--- a/app/src/main/res/layout/activity_oreo_autofill_filter.xml
+++ b/app/src/main/res/layout/activity_oreo_autofill_filter.xml
@@ -46,7 +46,7 @@
android:id="@+id/rvPasswordSwitcher"
android:layout_width="0dp"
android:layout_marginTop="@dimen/activity_vertical_margin"
- app:layout_constraintBottom_toTopOf="@id/shouldMatch"
+ app:layout_constraintBottom_toTopOf="@id/strictDomainSearch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/searchLayout"
@@ -72,6 +72,21 @@
</ViewSwitcher>
<Switch
+ android:id="@+id/strictDomainSearch"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/activity_horizontal_margin"
+ android:layout_marginTop="@dimen/activity_vertical_margin"
+ android:layout_marginEnd="@dimen/activity_horizontal_margin"
+ android:text="@string/oreo_autofill_strict_domain_search"
+ app:layout_constraintBottom_toTopOf="@id/shouldMatch"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/rvPasswordSwitcher"
+ app:layout_constraintVertical_bias="1.0"
+ tools:text="Phishing-resistant search"/>
+
+ <Switch
android:id="@+id/shouldMatch"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -82,7 +97,7 @@
app:layout_constraintBottom_toTopOf="@id/shouldClear"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/rvPasswordSwitcher"
+ app:layout_constraintTop_toBottomOf="@id/strictDomainSearch"
app:layout_constraintVertical_bias="1.0"
tools:text="Match with example.org" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7f22dc87..f0ba9048 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -250,6 +250,7 @@
<string name="folder_icon_hint">Folder icon</string>
<!-- Oreo Autofill -->
+ <string name="oreo_autofill_strict_domain_search">Phishing-resistant search</string>
<string name="oreo_autofill_match_with">Match with %1$s</string>
<string name="oreo_autofill_matches_clear_existing">Clear existing matches</string>
<string name="oreo_autofill_filter_no_results">No results.</string>