diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchController.kt index 71ea16bea..3a4e6aa5f 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchController.kt @@ -76,6 +76,7 @@ class DefaultSearchController( } override fun handleEditingCancelled() { + store.dispatch(SearchFragmentAction.UpdateEditingCanceled) navController.navigateUp() } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt index 696dffe79..ee340db1f 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt @@ -17,7 +17,9 @@ import android.view.ViewGroup import android.view.ViewStub import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible +import androidx.core.view.marginStart import androidx.fragment.app.Fragment +import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.navigation.fragment.findNavController import androidx.transition.TransitionInflater import kotlinx.android.synthetic.main.fragment_search.* @@ -111,7 +113,8 @@ class SearchFragment : Fragment(), UserInteractionHandler { showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions, session = session, pastedText = pastedText, - searchAccessPoint = searchAccessPoint + searchAccessPoint = searchAccessPoint, + isAnimatingOut = false ) ) } @@ -199,7 +202,7 @@ class SearchFragment : Fragment(), UserInteractionHandler { } view.back_button.setOnClickListener { - findNavController().navigateUp() + searchInteractor.onEditingCanceled() } val stubListener = ViewStub.OnInflateListener { _, inflated -> @@ -253,6 +256,7 @@ class SearchFragment : Fragment(), UserInteractionHandler { updateSearchWithLabel(it) updateClipboardSuggestion(it, requireContext().components.clipboardHandler.url) updateSearchSuggestionsHintVisibility(it) + updateBackButton(it) } startPostponedEnterTransition() @@ -316,6 +320,13 @@ class SearchFragment : Fragment(), UserInteractionHandler { clipboard_url.text = clipboardUrl } + private fun updateBackButton(searchState: SearchFragmentState) { + if (searchState.isAnimatingOut) { + searchStore.dispatch(SearchFragmentAction.ConsumeEditingCancelled) + animateBackButtonAway() + } + } + override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, @@ -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 { private const val SHARED_TRANSITION_MS = 200L private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1 diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt index f712ba8d6..a8687fde4 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchFragmentStore.kt @@ -57,13 +57,16 @@ data class SearchFragmentState( val showBookmarkSuggestions: Boolean, val session: Session?, val pastedText: String? = null, - val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint? + val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?, + val isAnimatingOut: Boolean ) : State /** * Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer. */ sealed class SearchFragmentAction : Action { + object UpdateEditingCanceled : SearchFragmentAction() + object ConsumeEditingCancelled : SearchFragmentAction() data class SearchShortcutEngineSelected(val engine: SearchEngine) : SearchFragmentAction() data class SelectNewDefaultSearchEngine(val engine: SearchEngine) : SearchFragmentAction() data class ShowSearchShortcutEnginePicker(val show: Boolean) : SearchFragmentAction() @@ -91,5 +94,9 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen ) is SearchFragmentAction.ShowSearchSuggestionsHint -> state.copy(showSearchSuggestionsHint = action.show) + is SearchFragmentAction.UpdateEditingCanceled -> + state.copy(isAnimatingOut = true) + is SearchFragmentAction.ConsumeEditingCancelled -> + state.copy(isAnimatingOut = false) } } diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt index 061805ac2..0c510ee52 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchFragmentStoreTest.kt @@ -58,6 +58,7 @@ class SearchFragmentStoreTest { showHistorySuggestions = false, showBookmarkSuggestions = false, session = null, - searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE + searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.NONE, + isAnimatingOut = false ) } diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchInteractorTest.kt index bdf7bb4ee..a2b98bde1 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchInteractorTest.kt @@ -13,8 +13,8 @@ import io.mockk.Runs import io.mockk.every import io.mockk.just import io.mockk.mockk -import io.mockk.verify import io.mockk.mockkObject +import io.mockk.verify import mozilla.components.browser.search.SearchEngine import mozilla.components.browser.search.SearchEngineManager import mozilla.components.browser.session.Session @@ -85,7 +85,7 @@ class SearchInteractorTest { @Test fun onEditingCanceled() { val navController: NavController = mockk(relaxed = true) - val store: SearchFragmentStore = mockk() + val store: SearchFragmentStore = mockk(relaxed = true) every { store.state } returns mockk(relaxed = true) @@ -99,6 +99,7 @@ class SearchInteractorTest { interactor.onEditingCanceled() verify { + store.dispatch(SearchFragmentAction.UpdateEditingCanceled) navController.navigateUp() } } diff --git a/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetConsoleReport.kt b/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetConsoleReport.kt index de83c3d5c..1ee6cebfc 100644 --- a/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetConsoleReport.kt +++ b/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetConsoleReport.kt @@ -3,7 +3,7 @@ package org.mozilla.fenix.detektrules import io.gitlab.arturbosch.detekt.api.ConsoleReport import io.gitlab.arturbosch.detekt.api.Detektion -class CustomRulesetConsoleReport: ConsoleReport() { +class CustomRulesetConsoleReport : ConsoleReport() { override fun render(detektion: Detektion): String? { return detektion.findings["mozilla-detekt-rules"]?.fold("") { output, finding -> output + finding.locationAsString + ": " + finding.messageOrDescription() diff --git a/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetProvider.kt b/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetProvider.kt index 887170f7b..7899a60b3 100644 --- a/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetProvider.kt +++ b/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/CustomRulesetProvider.kt @@ -8,7 +8,7 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.api.RuleSet import io.gitlab.arturbosch.detekt.api.RuleSetProvider -class CustomRulesetProvider: RuleSetProvider { +class CustomRulesetProvider : RuleSetProvider { override val ruleSetId: String = "mozilla-detekt-rules" override fun instance(config: Config): RuleSet = RuleSet( @@ -17,6 +17,4 @@ class CustomRulesetProvider: RuleSetProvider { MozillaBannedPropertyAccess(config) ) ) - - } diff --git a/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/MozillaBannedPropertyAccess.kt b/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/MozillaBannedPropertyAccess.kt index f9cc9ba62..c21eef6f1 100644 --- a/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/MozillaBannedPropertyAccess.kt +++ b/mozilla-detekt-rules/src/main/java/org/mozilla/fenix/detektrules/MozillaBannedPropertyAccess.kt @@ -13,7 +13,7 @@ import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity 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( "MozillaBannedPropertyAccess", Severity.Defect, @@ -27,7 +27,6 @@ class MozillaBannedPropertyAccess(config: Config = Config.empty): Rule(config) { listOf() } else { bannedPropertiesList.split(",") - } } @@ -44,7 +43,7 @@ class MozillaBannedPropertyAccess(config: Config = Config.empty): Rule(config) { CodeSmell( issue, 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) } }