* For #7698: Adds search back button animation * Refactor for searchControllermaster
parent
2372ee6b15
commit
20396f78a9
|
@ -76,6 +76,7 @@ class DefaultSearchController(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleEditingCancelled() {
|
override fun handleEditingCancelled() {
|
||||||
|
store.dispatch(SearchFragmentAction.UpdateEditingCanceled)
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,9 @@ import android.view.ViewGroup
|
||||||
import android.view.ViewStub
|
import android.view.ViewStub
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.view.marginStart
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.transition.TransitionInflater
|
import androidx.transition.TransitionInflater
|
||||||
import kotlinx.android.synthetic.main.fragment_search.*
|
import kotlinx.android.synthetic.main.fragment_search.*
|
||||||
|
@ -111,7 +113,8 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions,
|
showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions,
|
||||||
session = session,
|
session = session,
|
||||||
pastedText = pastedText,
|
pastedText = pastedText,
|
||||||
searchAccessPoint = searchAccessPoint
|
searchAccessPoint = searchAccessPoint,
|
||||||
|
isAnimatingOut = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -199,7 +202,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
view.back_button.setOnClickListener {
|
view.back_button.setOnClickListener {
|
||||||
findNavController().navigateUp()
|
searchInteractor.onEditingCanceled()
|
||||||
}
|
}
|
||||||
|
|
||||||
val stubListener = ViewStub.OnInflateListener { _, inflated ->
|
val stubListener = ViewStub.OnInflateListener { _, inflated ->
|
||||||
|
@ -253,6 +256,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
updateSearchWithLabel(it)
|
updateSearchWithLabel(it)
|
||||||
updateClipboardSuggestion(it, requireContext().components.clipboardHandler.url)
|
updateClipboardSuggestion(it, requireContext().components.clipboardHandler.url)
|
||||||
updateSearchSuggestionsHintVisibility(it)
|
updateSearchSuggestionsHintVisibility(it)
|
||||||
|
updateBackButton(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
startPostponedEnterTransition()
|
startPostponedEnterTransition()
|
||||||
|
@ -316,6 +320,13 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
clipboard_url.text = clipboardUrl
|
clipboard_url.text = clipboardUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateBackButton(searchState: SearchFragmentState) {
|
||||||
|
if (searchState.isAnimatingOut) {
|
||||||
|
searchStore.dispatch(SearchFragmentAction.ConsumeEditingCancelled)
|
||||||
|
animateBackButtonAway()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(
|
override fun onRequestPermissionsResult(
|
||||||
requestCode: Int,
|
requestCode: Int,
|
||||||
permissions: Array<String>,
|
permissions: Array<String>,
|
||||||
|
@ -352,6 +363,18 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun animateBackButtonAway() {
|
||||||
|
val backButton = requireView().back_button
|
||||||
|
val xTranslation = with(backButton) {
|
||||||
|
-(width + marginStart + paddingStart).toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
backButton
|
||||||
|
.animate()
|
||||||
|
.translationX(xTranslation)
|
||||||
|
.interpolator = FastOutSlowInInterpolator()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val SHARED_TRANSITION_MS = 200L
|
private const val SHARED_TRANSITION_MS = 200L
|
||||||
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
|
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
|
||||||
|
|
|
@ -57,13 +57,16 @@ data class SearchFragmentState(
|
||||||
val showBookmarkSuggestions: Boolean,
|
val showBookmarkSuggestions: Boolean,
|
||||||
val session: Session?,
|
val session: Session?,
|
||||||
val pastedText: String? = null,
|
val pastedText: String? = null,
|
||||||
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?
|
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?,
|
||||||
|
val isAnimatingOut: Boolean
|
||||||
) : State
|
) : State
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer.
|
* Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer.
|
||||||
*/
|
*/
|
||||||
sealed class SearchFragmentAction : Action {
|
sealed class SearchFragmentAction : Action {
|
||||||
|
object UpdateEditingCanceled : SearchFragmentAction()
|
||||||
|
object ConsumeEditingCancelled : SearchFragmentAction()
|
||||||
data class SearchShortcutEngineSelected(val engine: SearchEngine) : SearchFragmentAction()
|
data class SearchShortcutEngineSelected(val engine: SearchEngine) : SearchFragmentAction()
|
||||||
data class SelectNewDefaultSearchEngine(val engine: SearchEngine) : SearchFragmentAction()
|
data class SelectNewDefaultSearchEngine(val engine: SearchEngine) : SearchFragmentAction()
|
||||||
data class ShowSearchShortcutEnginePicker(val show: Boolean) : SearchFragmentAction()
|
data class ShowSearchShortcutEnginePicker(val show: Boolean) : SearchFragmentAction()
|
||||||
|
@ -91,5 +94,9 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
|
||||||
)
|
)
|
||||||
is SearchFragmentAction.ShowSearchSuggestionsHint ->
|
is SearchFragmentAction.ShowSearchSuggestionsHint ->
|
||||||
state.copy(showSearchSuggestionsHint = action.show)
|
state.copy(showSearchSuggestionsHint = action.show)
|
||||||
|
is SearchFragmentAction.UpdateEditingCanceled ->
|
||||||
|
state.copy(isAnimatingOut = true)
|
||||||
|
is SearchFragmentAction.ConsumeEditingCancelled ->
|
||||||
|
state.copy(isAnimatingOut = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ class SearchFragmentStoreTest {
|
||||||
showHistorySuggestions = false,
|
showHistorySuggestions = false,
|
||||||
showBookmarkSuggestions = false,
|
showBookmarkSuggestions = false,
|
||||||
session = null,
|
session = null,
|
||||||
searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE
|
searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE,
|
||||||
|
isAnimatingOut = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ import io.mockk.Runs
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.just
|
import io.mockk.just
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
|
||||||
import io.mockk.mockkObject
|
import io.mockk.mockkObject
|
||||||
|
import io.mockk.verify
|
||||||
import mozilla.components.browser.search.SearchEngine
|
import mozilla.components.browser.search.SearchEngine
|
||||||
import mozilla.components.browser.search.SearchEngineManager
|
import mozilla.components.browser.search.SearchEngineManager
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
|
@ -85,7 +85,7 @@ class SearchInteractorTest {
|
||||||
@Test
|
@Test
|
||||||
fun onEditingCanceled() {
|
fun onEditingCanceled() {
|
||||||
val navController: NavController = mockk(relaxed = true)
|
val navController: NavController = mockk(relaxed = true)
|
||||||
val store: SearchFragmentStore = mockk()
|
val store: SearchFragmentStore = mockk(relaxed = true)
|
||||||
|
|
||||||
every { store.state } returns mockk(relaxed = true)
|
every { store.state } returns mockk(relaxed = true)
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ class SearchInteractorTest {
|
||||||
interactor.onEditingCanceled()
|
interactor.onEditingCanceled()
|
||||||
|
|
||||||
verify {
|
verify {
|
||||||
|
store.dispatch(SearchFragmentAction.UpdateEditingCanceled)
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package org.mozilla.fenix.detektrules
|
||||||
import io.gitlab.arturbosch.detekt.api.ConsoleReport
|
import io.gitlab.arturbosch.detekt.api.ConsoleReport
|
||||||
import io.gitlab.arturbosch.detekt.api.Detektion
|
import io.gitlab.arturbosch.detekt.api.Detektion
|
||||||
|
|
||||||
class CustomRulesetConsoleReport: ConsoleReport() {
|
class CustomRulesetConsoleReport : ConsoleReport() {
|
||||||
override fun render(detektion: Detektion): String? {
|
override fun render(detektion: Detektion): String? {
|
||||||
return detektion.findings["mozilla-detekt-rules"]?.fold("") { output, finding ->
|
return detektion.findings["mozilla-detekt-rules"]?.fold("") { output, finding ->
|
||||||
output + finding.locationAsString + ": " + finding.messageOrDescription()
|
output + finding.locationAsString + ": " + finding.messageOrDescription()
|
||||||
|
|
|
@ -8,7 +8,7 @@ import io.gitlab.arturbosch.detekt.api.Config
|
||||||
import io.gitlab.arturbosch.detekt.api.RuleSet
|
import io.gitlab.arturbosch.detekt.api.RuleSet
|
||||||
import io.gitlab.arturbosch.detekt.api.RuleSetProvider
|
import io.gitlab.arturbosch.detekt.api.RuleSetProvider
|
||||||
|
|
||||||
class CustomRulesetProvider: RuleSetProvider {
|
class CustomRulesetProvider : RuleSetProvider {
|
||||||
override val ruleSetId: String = "mozilla-detekt-rules"
|
override val ruleSetId: String = "mozilla-detekt-rules"
|
||||||
|
|
||||||
override fun instance(config: Config): RuleSet = RuleSet(
|
override fun instance(config: Config): RuleSet = RuleSet(
|
||||||
|
@ -17,6 +17,4 @@ class CustomRulesetProvider: RuleSetProvider {
|
||||||
MozillaBannedPropertyAccess(config)
|
MozillaBannedPropertyAccess(config)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import io.gitlab.arturbosch.detekt.api.Rule
|
||||||
import io.gitlab.arturbosch.detekt.api.Severity
|
import io.gitlab.arturbosch.detekt.api.Severity
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
class MozillaBannedPropertyAccess(config: Config = Config.empty): Rule(config) {
|
class MozillaBannedPropertyAccess(config: Config = Config.empty) : Rule(config) {
|
||||||
override val issue = Issue(
|
override val issue = Issue(
|
||||||
"MozillaBannedPropertyAccess",
|
"MozillaBannedPropertyAccess",
|
||||||
Severity.Defect,
|
Severity.Defect,
|
||||||
|
@ -27,7 +27,6 @@ class MozillaBannedPropertyAccess(config: Config = Config.empty): Rule(config) {
|
||||||
listOf<String>()
|
listOf<String>()
|
||||||
} else {
|
} else {
|
||||||
bannedPropertiesList.split(",")
|
bannedPropertiesList.split(",")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ class MozillaBannedPropertyAccess(config: Config = Config.empty): Rule(config) {
|
||||||
CodeSmell(
|
CodeSmell(
|
||||||
issue,
|
issue,
|
||||||
Entity.from(expression),
|
Entity.from(expression),
|
||||||
"Using ${possiblyBannedPropertyAccess} is not allowed because accessing property ${it} is against Mozilla policy. See 'mozilla-detekt-rules' stanza in 'config/detekt.yml' for more information.\n"
|
"Using $possiblyBannedPropertyAccess is not allowed because accessing property $it is against Mozilla policy. See 'mozilla-detekt-rules' stanza in 'config/detekt.yml' for more information.\n"
|
||||||
)
|
)
|
||||||
}.forEach { report(it) }
|
}.forEach { report(it) }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue