feat: Toggle display of search operators with toolbar action (#836)
Default to hiding the search operators, and provide a new toolbar icon (always visible) to show them. The toolbar icon is displayed with a badge if any operators are present. Adjust the operator display to three horizontal scrolling rows, to further limit the maximum amount of vertical space the operators use.
This commit is contained in:
parent
5d574d4d76
commit
01831474dc
|
@ -105,7 +105,7 @@
|
||||||
line="388"
|
line="388"
|
||||||
column="28"/>
|
column="28"/>
|
||||||
<location
|
<location
|
||||||
file="${:core:activity*buildDir}/generated/res/resValues/orangeFdroid/debug/values/gradleResValues.xml"
|
file="${:core:activity*buildDir}/generated/res/resValues/blueFdroid/debug/values/gradleResValues.xml"
|
||||||
line="7"
|
line="7"
|
||||||
column="5"
|
column="5"
|
||||||
message="This definition does not require arguments"/>
|
message="This definition does not require arguments"/>
|
||||||
|
@ -767,7 +767,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="282"
|
line="283"
|
||||||
column="5"/>
|
column="5"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -778,7 +778,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="333"
|
line="334"
|
||||||
column="5"/>
|
column="5"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -789,7 +789,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="452"
|
line="453"
|
||||||
column="5"/>
|
column="5"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="628"
|
line="629"
|
||||||
column="5"/>
|
column="5"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1196,7 +1196,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/donottranslate.xml"
|
file="src/main/res/values/donottranslate.xml"
|
||||||
line="273"
|
line="275"
|
||||||
column="19"/>
|
column="19"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1207,7 +1207,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/donottranslate.xml"
|
file="src/main/res/values/donottranslate.xml"
|
||||||
line="278"
|
line="280"
|
||||||
column="19"/>
|
column="19"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1372,7 +1372,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="198"
|
line="199"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1383,7 +1383,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="219"
|
line="220"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1394,7 +1394,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="220"
|
line="221"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1405,7 +1405,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="243"
|
line="244"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1416,7 +1416,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="272"
|
line="273"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1427,7 +1427,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="343"
|
line="344"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1438,7 +1438,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="383"
|
line="384"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1449,7 +1449,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="419"
|
line="420"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1460,7 +1460,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="422"
|
line="423"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1471,7 +1471,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="423"
|
line="424"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1482,7 +1482,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="424"
|
line="425"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1493,7 +1493,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="425"
|
line="426"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1504,7 +1504,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="426"
|
line="427"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1515,7 +1515,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="438"
|
line="439"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1526,7 +1526,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="439"
|
line="440"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1537,7 +1537,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="490"
|
line="491"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1548,7 +1548,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="491"
|
line="492"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1559,7 +1559,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="502"
|
line="503"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1570,7 +1570,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="503"
|
line="504"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1581,7 +1581,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="504"
|
line="505"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1592,7 +1592,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="507"
|
line="508"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1603,7 +1603,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="545"
|
line="546"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1614,7 +1614,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="586"
|
line="587"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1625,7 +1625,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="592"
|
line="593"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1636,7 +1636,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="620"
|
line="621"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -1647,7 +1647,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/strings.xml"
|
file="src/main/res/values/strings.xml"
|
||||||
line="646"
|
line="647"
|
||||||
column="13"/>
|
column="13"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.annotation.OptIn
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
|
@ -70,6 +71,7 @@ import app.pachli.components.search.adapter.SearchPagerAdapter
|
||||||
import app.pachli.core.activity.BottomSheetActivity
|
import app.pachli.core.activity.BottomSheetActivity
|
||||||
import app.pachli.core.common.extensions.hide
|
import app.pachli.core.common.extensions.hide
|
||||||
import app.pachli.core.common.extensions.show
|
import app.pachli.core.common.extensions.show
|
||||||
|
import app.pachli.core.common.extensions.toggleVisibility
|
||||||
import app.pachli.core.common.extensions.viewBinding
|
import app.pachli.core.common.extensions.viewBinding
|
||||||
import app.pachli.core.common.extensions.visible
|
import app.pachli.core.common.extensions.visible
|
||||||
import app.pachli.core.network.Server
|
import app.pachli.core.network.Server
|
||||||
|
@ -98,7 +100,11 @@ import app.pachli.databinding.SearchOperatorDateDialogBinding
|
||||||
import app.pachli.databinding.SearchOperatorFromDialogBinding
|
import app.pachli.databinding.SearchOperatorFromDialogBinding
|
||||||
import app.pachli.databinding.SearchOperatorWhereLocationDialogBinding
|
import app.pachli.databinding.SearchOperatorWhereLocationDialogBinding
|
||||||
import com.github.michaelbull.result.get
|
import com.github.michaelbull.result.get
|
||||||
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
|
import com.google.android.material.badge.BadgeUtils
|
||||||
|
import com.google.android.material.badge.ExperimentalBadgeUtils
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.datepicker.CalendarConstraints
|
import com.google.android.material.datepicker.CalendarConstraints
|
||||||
import com.google.android.material.datepicker.DateValidatorPointBackward
|
import com.google.android.material.datepicker.DateValidatorPointBackward
|
||||||
import com.google.android.material.datepicker.MaterialDatePicker
|
import com.google.android.material.datepicker.MaterialDatePicker
|
||||||
|
@ -125,6 +131,9 @@ class SearchActivity :
|
||||||
|
|
||||||
private lateinit var searchView: SearchView
|
private lateinit var searchView: SearchView
|
||||||
|
|
||||||
|
val showFilterIcon: Boolean
|
||||||
|
get() = viewModel.availableOperators.value.isNotEmpty()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
@ -156,6 +165,7 @@ class SearchActivity :
|
||||||
* Binds the initial search operator chips UI and updates as the search
|
* Binds the initial search operator chips UI and updates as the search
|
||||||
* operators change.
|
* operators change.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalBadgeUtils::class)
|
||||||
private fun bindOperators() {
|
private fun bindOperators() {
|
||||||
val viewDataToChip: Map<Class<out SearchOperatorViewData<SearchOperator>>, Chip> = mapOf(
|
val viewDataToChip: Map<Class<out SearchOperatorViewData<SearchOperator>>, Chip> = mapOf(
|
||||||
DateOperatorViewData::class.java to binding.chipDate,
|
DateOperatorViewData::class.java to binding.chipDate,
|
||||||
|
@ -170,6 +180,18 @@ class SearchActivity :
|
||||||
WhereOperatorViewData::class.java to binding.chipWhere,
|
WhereOperatorViewData::class.java to binding.chipWhere,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Chips are initially hidden, toggled by the "filter" button
|
||||||
|
binding.chipsFilter.hide()
|
||||||
|
binding.chipsFilter2.hide()
|
||||||
|
binding.chipsFilter3.hide()
|
||||||
|
|
||||||
|
// Badge to draw on the filter button if any filters are active.
|
||||||
|
val filterBadgeDrawable = BadgeDrawable.create(this).apply {
|
||||||
|
text = "!"
|
||||||
|
backgroundColor = MaterialColors.getColor(binding.toolbar, com.google.android.material.R.attr.colorPrimary)
|
||||||
|
}
|
||||||
|
BadgeUtils.attachBadgeDrawable(filterBadgeDrawable, binding.toolbar, R.id.action_filter_search)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
launch {
|
launch {
|
||||||
|
@ -189,17 +211,28 @@ class SearchActivity :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.availableOperators.collectLatest {
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
setSearchViewWidth(showFilterIcon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.operatorViewData.collectLatest { operators ->
|
viewModel.operatorViewData.collectLatest { operators ->
|
||||||
|
var showFilterBadgeDrawable = false
|
||||||
|
|
||||||
operators.forEach { viewData ->
|
operators.forEach { viewData ->
|
||||||
viewDataToChip[viewData::class.java]?.let { chip ->
|
viewDataToChip[viewData::class.java]?.let { chip ->
|
||||||
|
showFilterBadgeDrawable = showFilterBadgeDrawable or (viewData.operator.choice != null)
|
||||||
chip.isChecked = viewData.operator.choice != null
|
chip.isChecked = viewData.operator.choice != null
|
||||||
chip.setCloseIconVisible(viewData.operator.choice != null)
|
chip.setCloseIconVisible(viewData.operator.choice != null)
|
||||||
chip.text = viewData.chipLabel(this@SearchActivity)
|
chip.text = viewData.chipLabel(this@SearchActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.search()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterBadgeDrawable.setVisible(showFilterBadgeDrawable)
|
||||||
|
viewModel.search()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,15 +966,35 @@ class SearchActivity :
|
||||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
super.onCreateMenu(menu, menuInflater)
|
super.onCreateMenu(menu, menuInflater)
|
||||||
menuInflater.inflate(R.menu.search_toolbar, menu)
|
menuInflater.inflate(R.menu.search_toolbar, menu)
|
||||||
|
|
||||||
|
menu.findItem(R.id.action_filter_search)?.apply {
|
||||||
|
icon = makeIcon(this@SearchActivity, GoogleMaterial.Icon.gmd_tune, IconicsSize.dp(20))
|
||||||
|
}
|
||||||
|
|
||||||
val searchViewMenuItem = menu.findItem(R.id.action_search)
|
val searchViewMenuItem = menu.findItem(R.id.action_search)
|
||||||
searchViewMenuItem.expandActionView()
|
searchViewMenuItem.expandActionView()
|
||||||
searchView = searchViewMenuItem.actionView as SearchView
|
searchView = searchViewMenuItem.actionView as SearchView
|
||||||
bindSearchView()
|
bindSearchView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPrepareMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.action_filter_search)?.apply {
|
||||||
|
isVisible = showFilterIcon
|
||||||
|
}
|
||||||
|
return super<BottomSheetActivity>.onPrepareMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||||
super.onMenuItemSelected(menuItem)
|
return when (menuItem.itemId) {
|
||||||
return false
|
R.id.action_filter_search -> {
|
||||||
|
binding.chipsFilter.toggleVisibility()
|
||||||
|
binding.chipsFilter2.toggleVisibility()
|
||||||
|
binding.chipsFilter3.toggleVisibility()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> super.onMenuItemSelected(menuItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPageTitle(position: Int): CharSequence {
|
private fun getPageTitle(position: Int): CharSequence {
|
||||||
|
@ -965,6 +1018,27 @@ class SearchActivity :
|
||||||
searchView.setIconifiedByDefault(false)
|
searchView.setIconifiedByDefault(false)
|
||||||
searchView.setSearchableInfo((getSystemService(Context.SEARCH_SERVICE) as? SearchManager)?.getSearchableInfo(componentName))
|
searchView.setSearchableInfo((getSystemService(Context.SEARCH_SERVICE) as? SearchManager)?.getSearchableInfo(componentName))
|
||||||
|
|
||||||
|
setSearchViewWidth(showFilterIcon)
|
||||||
|
|
||||||
|
// Keep text that was entered also when switching to a different tab (before the search is executed)
|
||||||
|
searchView.setOnQueryTextListener(this)
|
||||||
|
searchView.setQuery(viewModel.currentSearchFieldContent ?: "", false)
|
||||||
|
|
||||||
|
// Only focus if the query is empty. This ensures that if the user is returning
|
||||||
|
// to the search results after visiting a result the full list is available,
|
||||||
|
// instead of being obscured by the keyboard.
|
||||||
|
if (viewModel.currentQuery.isBlank()) searchView.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute and set the width of [searchView].
|
||||||
|
*
|
||||||
|
* @param showingFilterIcon True if the filter icon is showing and the width should
|
||||||
|
* be adjusted to account for this.
|
||||||
|
*/
|
||||||
|
private fun setSearchViewWidth(showingFilterIcon: Boolean) {
|
||||||
|
if (!this::searchView.isInitialized) return
|
||||||
|
|
||||||
// SearchView has a bug. If it's displayed 'app:showAsAction="always"' it's too wide,
|
// SearchView has a bug. If it's displayed 'app:showAsAction="always"' it's too wide,
|
||||||
// pushing other icons (including the options menu '...' icon) off the edge of the
|
// pushing other icons (including the options menu '...' icon) off the edge of the
|
||||||
// screen.
|
// screen.
|
||||||
|
@ -986,20 +1060,11 @@ class SearchActivity :
|
||||||
// It appears to be impossible to override this behaviour on API level < 33.
|
// It appears to be impossible to override this behaviour on API level < 33.
|
||||||
//
|
//
|
||||||
// SearchView does allow you to specify the maximum width. So take the screen width,
|
// SearchView does allow you to specify the maximum width. So take the screen width,
|
||||||
// subtract 48dp * 2 (for the menu icon and back icon on either side), convert to pixels,
|
// subtract 48dp * iconCount (for the menu, filter, and back icons), convert to pixels, and use that.
|
||||||
// and use that.
|
val iconCount = if (showingFilterIcon) 3 else 2
|
||||||
val pxScreenWidth = resources.displayMetrics.widthPixels
|
val pxScreenWidth = resources.displayMetrics.widthPixels
|
||||||
val pxBuffer = ((48 * 2) * resources.displayMetrics.density).toInt()
|
val pxBuffer = ((48 * iconCount) * resources.displayMetrics.density).toInt()
|
||||||
searchView.maxWidth = pxScreenWidth - pxBuffer
|
searchView.maxWidth = pxScreenWidth - pxBuffer
|
||||||
|
|
||||||
// Keep text that was entered also when switching to a different tab (before the search is executed)
|
|
||||||
searchView.setOnQueryTextListener(this)
|
|
||||||
searchView.setQuery(viewModel.currentSearchFieldContent ?: "", false)
|
|
||||||
|
|
||||||
// Only focus if the query is empty. This ensures that if the user is returning
|
|
||||||
// to the search results after visiting a result the full list is available,
|
|
||||||
// instead of being obscured by the keyboard.
|
|
||||||
if (viewModel.currentQuery.isBlank()) searchView.requestFocus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||||
|
|
|
@ -36,6 +36,20 @@ import app.pachli.components.search.adapter.SearchPagingSourceFactory
|
||||||
import app.pachli.core.accounts.AccountManager
|
import app.pachli.core.accounts.AccountManager
|
||||||
import app.pachli.core.data.repository.ServerRepository
|
import app.pachli.core.data.repository.ServerRepository
|
||||||
import app.pachli.core.database.model.AccountEntity
|
import app.pachli.core.database.model.AccountEntity
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_FROM
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE
|
||||||
|
import app.pachli.core.network.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
|
||||||
import app.pachli.core.network.model.DeletedStatus
|
import app.pachli.core.network.model.DeletedStatus
|
||||||
import app.pachli.core.network.model.Poll
|
import app.pachli.core.network.model.Poll
|
||||||
import app.pachli.core.network.model.Status
|
import app.pachli.core.network.model.Status
|
||||||
|
@ -47,7 +61,9 @@ import app.pachli.viewdata.StatusViewData
|
||||||
import at.connyduck.calladapter.networkresult.NetworkResult
|
import at.connyduck.calladapter.networkresult.NetworkResult
|
||||||
import at.connyduck.calladapter.networkresult.fold
|
import at.connyduck.calladapter.networkresult.fold
|
||||||
import at.connyduck.calladapter.networkresult.onFailure
|
import at.connyduck.calladapter.networkresult.onFailure
|
||||||
|
import com.github.michaelbull.result.mapBoth
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import io.github.z4kn4fein.semver.constraints.toConstraint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
@ -118,6 +134,68 @@ class SearchViewModel @Inject constructor(
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of operators the server supports.
|
||||||
|
*
|
||||||
|
* Empty set if the server does not support any operators.
|
||||||
|
*/
|
||||||
|
val availableOperators = serverRepository.flow.map { result ->
|
||||||
|
result.mapBoth(
|
||||||
|
{ server ->
|
||||||
|
buildSet {
|
||||||
|
val constraint100 = ">=1.0.0".toConstraint()
|
||||||
|
val canHasMedia = server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_MEDIA, constraint100)
|
||||||
|
val canHasImage = server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_IMAGE, constraint100)
|
||||||
|
val canHasVideo = server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_VIDEO, constraint100)
|
||||||
|
val canHasAudio = server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_AUDIO, constraint100)
|
||||||
|
if (canHasMedia || canHasImage || canHasVideo || canHasAudio) {
|
||||||
|
add(HasMediaOperator())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_BY_DATE, constraint100)) {
|
||||||
|
add(DateOperator())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_FROM, constraint100)) {
|
||||||
|
add(FromOperator())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE, constraint100)) {
|
||||||
|
add(LanguageOperator())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_LINK, constraint100)) {
|
||||||
|
add(HasLinkOperator())
|
||||||
|
}
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_EMBED, constraint100)) {
|
||||||
|
add(HasEmbedOperator())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_HAS_POLL, constraint100)) {
|
||||||
|
add(HasPollOperator())
|
||||||
|
}
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_IS_REPLY, constraint100)) {
|
||||||
|
add(IsReplyOperator())
|
||||||
|
}
|
||||||
|
if (server.can(ORG_JOINMASTODON_SEARCH_QUERY_IS_SENSITIVE, constraint100)) {
|
||||||
|
add(IsSensitiveOperator())
|
||||||
|
}
|
||||||
|
|
||||||
|
val canInLibrary = server.can(ORG_JOINMASTODON_SEARCH_QUERY_IN_LIBRARY, constraint100)
|
||||||
|
val canInPublic = server.can(ORG_JOINMASTODON_SEARCH_QUERY_IN_PUBLIC, constraint100)
|
||||||
|
if (canInLibrary || canInPublic) add(WhereOperator())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
emptySet()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}.stateIn(
|
||||||
|
viewModelScope,
|
||||||
|
SharingStarted.WhileSubscribed(5000),
|
||||||
|
emptySet(),
|
||||||
|
)
|
||||||
|
|
||||||
private val loadedStatuses: MutableList<StatusViewData> = mutableListOf()
|
private val loadedStatuses: MutableList<StatusViewData> = mutableListOf()
|
||||||
|
|
||||||
private val statusesPagingSourceFactory = SearchPagingSourceFactory(mastodonApi, SearchType.Status, loadedStatuses) {
|
private val statusesPagingSourceFactory = SearchPagingSourceFactory(mastodonApi, SearchType.Status, loadedStatuses) {
|
||||||
|
@ -162,7 +240,7 @@ class SearchViewModel @Inject constructor(
|
||||||
* with [viewData].
|
* with [viewData].
|
||||||
*/
|
*/
|
||||||
fun <T : SearchOperator> replaceOperator(viewData: SearchOperatorViewData<T>) = _operatorViewData.update { operators ->
|
fun <T : SearchOperator> replaceOperator(viewData: SearchOperatorViewData<T>) = _operatorViewData.update { operators ->
|
||||||
operators.find { it.javaClass == viewData.javaClass }?.let { operators - it + viewData } ?: (operators + viewData)
|
operators.find { it.javaClass == viewData.javaClass }?.let { operators - it + viewData } ?: operators
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search() {
|
fun search() {
|
||||||
|
|
|
@ -21,100 +21,141 @@
|
||||||
app:layout_scrollFlags="scroll|snap|enterAlways"
|
app:layout_scrollFlags="scroll|snap|enterAlways"
|
||||||
app:navigationIcon="?attr/homeAsUpIndicator" />
|
app:navigationIcon="?attr/homeAsUpIndicator" />
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
<HorizontalScrollView
|
||||||
android:id="@+id/chipsFilter"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="?listPreferredItemPaddingStart"
|
|
||||||
android:paddingEnd="?listPreferredItemPaddingEnd"
|
|
||||||
app:layout_scrollFlags="scroll|snap|enterAlways"
|
app:layout_scrollFlags="scroll|snap|enterAlways"
|
||||||
android:animateLayoutChanges="true">
|
android:scrollbars="none">
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/chipFrom"
|
android:id="@+id/chipsFilter"
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:chipIconEnabled="true"
|
android:paddingStart="?listPreferredItemPaddingStart"
|
||||||
android:text="@string/search_operator_from_all" />
|
android:paddingEnd="?listPreferredItemPaddingEnd"
|
||||||
|
app:singleLine="true"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/chipDate"
|
android:id="@+id/chipFrom"
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_from_all" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chipDate"
|
||||||
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_date_all" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chipLanguage"
|
||||||
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_language_all" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chipWhere"
|
||||||
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_where_all" />
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_scrollFlags="scroll|snap|enterAlways"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/chipsFilter2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:chipIconEnabled="true"
|
android:paddingStart="?listPreferredItemPaddingStart"
|
||||||
android:text="@string/search_operator_date_all" />
|
android:paddingEnd="?listPreferredItemPaddingEnd"
|
||||||
|
app:singleLine="true"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/chipLanguage"
|
android:id="@+id/chip_has_media"
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIcon="@drawable/ic_attach_file_24dp"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_attachment_all" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chip_has_poll"
|
||||||
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIcon="@drawable/ic_attach_file_24dp"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_poll_all" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chip_has_link"
|
||||||
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIcon="@drawable/ic_link_24"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_link_all" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chip_has_embed"
|
||||||
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIconEnabled="true"
|
||||||
|
android:text="@string/search_operator_embed_all" />
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_scrollFlags="scroll|snap|enterAlways"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/chipsFilter3"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:chipIconEnabled="true"
|
android:paddingStart="?listPreferredItemPaddingStart"
|
||||||
android:text="@string/search_operator_language_all" />
|
android:paddingEnd="?listPreferredItemPaddingEnd"
|
||||||
|
app:singleLine="true"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/chip_has_media"
|
android:id="@+id/chip_is_reply"
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:chipIcon="@drawable/ic_attach_file_24dp"
|
app:chipIcon="@drawable/ic_reply_all_24dp"
|
||||||
app:chipIconEnabled="true"
|
app:chipIconEnabled="true"
|
||||||
android:text="@string/search_operator_attachment_all" />
|
android:text="@string/search_operator_replies_all" />
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/chip_is_reply"
|
android:id="@+id/chip_is_sensitive"
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
style="@style/Widget.Material3.Chip.Suggestion"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:chipIcon="@drawable/ic_reply_all_24dp"
|
app:chipIcon="@drawable/ic_eye_24dp"
|
||||||
app:chipIconEnabled="true"
|
app:chipIconEnabled="true"
|
||||||
android:text="@string/search_operator_replies_all" />
|
android:text="@string/search_operator_sensitive_all" />
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
<com.google.android.material.chip.Chip
|
</HorizontalScrollView>
|
||||||
android:id="@+id/chip_is_sensitive"
|
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:chipIcon="@drawable/ic_eye_24dp"
|
|
||||||
app:chipIconEnabled="true"
|
|
||||||
android:text="@string/search_operator_sensitive_all" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/chip_has_poll"
|
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:chipIcon="@drawable/ic_attach_file_24dp"
|
|
||||||
app:chipIconEnabled="true"
|
|
||||||
android:text="@string/search_operator_poll_all" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/chip_has_embed"
|
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:chipIconEnabled="true"
|
|
||||||
android:text="@string/search_operator_embed_all" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/chip_has_link"
|
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:chipIcon="@drawable/ic_link_24"
|
|
||||||
app:chipIconEnabled="true"
|
|
||||||
android:text="@string/search_operator_link_all" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/chipWhere"
|
|
||||||
style="@style/Widget.Material3.Chip.Suggestion"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:chipIconEnabled="true"
|
|
||||||
android:text="@string/search_operator_where_all" />
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:id="@+id/tabs"
|
android:id="@+id/tabs"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
|
@ -8,5 +9,12 @@
|
||||||
android:icon="@android:drawable/ic_menu_search"
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
android:actionLayout="@layout/search_view"
|
android:actionLayout="@layout/search_view"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always"
|
||||||
|
tools:ignore="AlwaysShowAction" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_filter_search"
|
||||||
|
android:title="@string/action_filter_search"
|
||||||
|
app:showAsAction="always"
|
||||||
|
tools:ignore="AlwaysShowAction" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -165,6 +165,7 @@
|
||||||
<string name="action_accept">Accept</string>
|
<string name="action_accept">Accept</string>
|
||||||
<string name="action_reject">Reject</string>
|
<string name="action_reject">Reject</string>
|
||||||
<string name="action_search">Search</string>
|
<string name="action_search">Search</string>
|
||||||
|
<string name="action_filter_search">Filter search</string>
|
||||||
<string name="action_access_drafts">Drafts</string>
|
<string name="action_access_drafts">Drafts</string>
|
||||||
<string name="action_access_scheduled_posts">Scheduled posts</string>
|
<string name="action_access_scheduled_posts">Scheduled posts</string>
|
||||||
<string name="action_toggle_visibility">Post visibility</string>
|
<string name="action_toggle_visibility">Post visibility</string>
|
||||||
|
|
|
@ -30,3 +30,11 @@ fun View.hide() {
|
||||||
fun View.visible(visible: Boolean, or: Int = View.GONE) {
|
fun View.visible(visible: Boolean, or: Int = View.GONE) {
|
||||||
this.visibility = if (visible) View.VISIBLE else or
|
this.visibility = if (visible) View.VISIBLE else or
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun View.toggleVisibility() {
|
||||||
|
when (this.visibility) {
|
||||||
|
View.GONE -> this.show()
|
||||||
|
View.INVISIBLE -> this.show()
|
||||||
|
View.VISIBLE -> this.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/styles.xml"
|
file="src/main/res/values/styles.xml"
|
||||||
line="134"
|
line="137"
|
||||||
column="42"/>
|
column="42"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
<location
|
<location
|
||||||
file="src/main/res/values/styles.xml"
|
file="src/main/res/values/styles.xml"
|
||||||
line="135"
|
line="138"
|
||||||
column="43"/>
|
column="43"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue