Add createInitialSearchFragmentState function
parent
3086d8a694
commit
1fab28f043
|
@ -30,7 +30,6 @@ import kotlinx.android.synthetic.main.fragment_search.*
|
||||||
import kotlinx.android.synthetic.main.fragment_search.view.*
|
import kotlinx.android.synthetic.main.fragment_search.view.*
|
||||||
import kotlinx.android.synthetic.main.search_suggestions_onboarding.view.*
|
import kotlinx.android.synthetic.main.search_suggestions_onboarding.view.*
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import mozilla.components.browser.state.selector.findTab
|
|
||||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||||
import mozilla.components.concept.storage.HistoryStorage
|
import mozilla.components.concept.storage.HistoryStorage
|
||||||
import mozilla.components.feature.qr.QrFeature
|
import mozilla.components.feature.qr.QrFeature
|
||||||
|
@ -55,6 +54,7 @@ import org.mozilla.fenix.ext.hideToolbar
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
|
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
|
||||||
|
import org.mozilla.fenix.search.ext.areShortcutsAvailable
|
||||||
import org.mozilla.fenix.search.toolbar.ToolbarView
|
import org.mozilla.fenix.search.toolbar.ToolbarView
|
||||||
import org.mozilla.fenix.settings.SupportUtils
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener
|
import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener
|
||||||
|
@ -71,14 +71,6 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
|
|
||||||
private val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
private val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
||||||
|
|
||||||
private fun shouldShowSearchSuggestions(isPrivate: Boolean): Boolean =
|
|
||||||
if (isPrivate) {
|
|
||||||
requireContext().settings().shouldShowSearchSuggestions &&
|
|
||||||
requireContext().settings().shouldShowSearchSuggestionsInPrivate
|
|
||||||
} else {
|
|
||||||
requireContext().settings().shouldShowSearchSuggestions
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -89,38 +81,18 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
val settings = activity.settings()
|
val settings = activity.settings()
|
||||||
val args by navArgs<SearchFragmentArgs>()
|
val args by navArgs<SearchFragmentArgs>()
|
||||||
|
|
||||||
val tabId = args.sessionId
|
|
||||||
val tab = tabId?.let { requireComponents.core.store.state.findTab(it) }
|
|
||||||
|
|
||||||
val view = inflater.inflate(R.layout.fragment_search, container, false)
|
val view = inflater.inflate(R.layout.fragment_search, container, false)
|
||||||
val url = tab?.content?.url.orEmpty()
|
|
||||||
val currentSearchEngine = SearchEngineSource.Default(
|
|
||||||
requireComponents.search.provider.getDefaultEngine(requireContext())
|
|
||||||
)
|
|
||||||
|
|
||||||
val isPrivate = activity.browsingModeManager.mode.isPrivate
|
val isPrivate = activity.browsingModeManager.mode.isPrivate
|
||||||
|
|
||||||
requireComponents.analytics.metrics.track(Event.InteractWithSearchURLArea)
|
requireComponents.analytics.metrics.track(Event.InteractWithSearchURLArea)
|
||||||
|
|
||||||
val areShortcutsAvailable = areShortcutsAvailable()
|
|
||||||
searchStore = StoreProvider.get(this) {
|
searchStore = StoreProvider.get(this) {
|
||||||
SearchFragmentStore(
|
SearchFragmentStore(
|
||||||
SearchFragmentState(
|
createInitialSearchFragmentState(
|
||||||
query = url,
|
activity,
|
||||||
url = url,
|
requireComponents,
|
||||||
searchTerms = tab?.content?.searchTerms.orEmpty(),
|
tabId = args.sessionId,
|
||||||
searchEngineSource = currentSearchEngine,
|
|
||||||
defaultEngineSource = currentSearchEngine,
|
|
||||||
showSearchSuggestions = shouldShowSearchSuggestions(isPrivate),
|
|
||||||
showSearchSuggestionsHint = false,
|
|
||||||
showSearchShortcuts = settings.shouldShowSearchShortcuts &&
|
|
||||||
url.isEmpty() &&
|
|
||||||
areShortcutsAvailable,
|
|
||||||
areShortcutsAvailable = areShortcutsAvailable,
|
|
||||||
showClipboardSuggestions = settings.shouldShowClipboardSuggestions,
|
|
||||||
showHistorySuggestions = settings.shouldShowHistorySuggestions,
|
|
||||||
showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions,
|
|
||||||
tabId = tabId,
|
|
||||||
pastedText = args.pastedText,
|
pastedText = args.pastedText,
|
||||||
searchAccessPoint = args.searchAccessPoint
|
searchAccessPoint = args.searchAccessPoint
|
||||||
)
|
)
|
||||||
|
@ -165,7 +137,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_microphone)!!,
|
ContextCompat.getDrawable(requireContext(), R.drawable.ic_microphone)!!,
|
||||||
requireContext().getString(R.string.voice_search_content_description),
|
requireContext().getString(R.string.voice_search_content_description),
|
||||||
visible = {
|
visible = {
|
||||||
currentSearchEngine.searchEngine.identifier.contains("google") &&
|
searchStore.state.searchEngineSource.searchEngine.identifier.contains("google") &&
|
||||||
speechIsAvailable() &&
|
speechIsAvailable() &&
|
||||||
settings.shouldShowVoiceSearch
|
settings.shouldShowVoiceSearch
|
||||||
},
|
},
|
||||||
|
@ -343,10 +315,11 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
|
val provider = requireComponents.search.provider
|
||||||
|
|
||||||
// The user has the option to go to 'Shortcuts' -> 'Search engine settings' to modify the default search engine.
|
// The user has the option to go to 'Shortcuts' -> 'Search engine settings' to modify the default search engine.
|
||||||
// When returning from that settings screen we need to update it to account for any changes.
|
// When returning from that settings screen we need to update it to account for any changes.
|
||||||
val currentDefaultEngine =
|
val currentDefaultEngine = provider.getDefaultEngine(requireContext())
|
||||||
requireComponents.search.provider.getDefaultEngine(requireContext())
|
|
||||||
|
|
||||||
if (searchStore.state.defaultEngineSource.searchEngine != currentDefaultEngine) {
|
if (searchStore.state.defaultEngineSource.searchEngine != currentDefaultEngine) {
|
||||||
searchStore.dispatch(
|
searchStore.dispatch(
|
||||||
|
@ -356,7 +329,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Users can from this fragment go to install/uninstall search engines and then return.
|
// Users can from this fragment go to install/uninstall search engines and then return.
|
||||||
val areShortcutsAvailable = areShortcutsAvailable()
|
val areShortcutsAvailable = provider.areShortcutsAvailable(requireContext())
|
||||||
if (searchStore.state.areShortcutsAvailable != areShortcutsAvailable) {
|
if (searchStore.state.areShortcutsAvailable != areShortcutsAvailable) {
|
||||||
searchStore.dispatch(SearchFragmentAction.UpdateShortcutsAvailability(areShortcutsAvailable))
|
searchStore.dispatch(SearchFragmentAction.UpdateShortcutsAvailability(areShortcutsAvailable))
|
||||||
}
|
}
|
||||||
|
@ -367,7 +340,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
|
|
||||||
updateClipboardSuggestion(
|
updateClipboardSuggestion(
|
||||||
searchStore.state,
|
searchStore.state,
|
||||||
requireContext().components.clipboardHandler.url
|
requireComponents.clipboardHandler.url
|
||||||
)
|
)
|
||||||
|
|
||||||
permissionDidUpdate = false
|
permissionDidUpdate = false
|
||||||
|
@ -470,16 +443,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return if the user has *at least 2* installed search engines.
|
|
||||||
* Useful to decide whether to show / enable certain functionalities.
|
|
||||||
*/
|
|
||||||
private fun areShortcutsAvailable() =
|
|
||||||
requireContext().components.search.provider.installedSearchEngines(requireContext())
|
|
||||||
.list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
|
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
|
||||||
private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,15 @@
|
||||||
package org.mozilla.fenix.search
|
package org.mozilla.fenix.search
|
||||||
|
|
||||||
import mozilla.components.browser.search.SearchEngine
|
import mozilla.components.browser.search.SearchEngine
|
||||||
|
import mozilla.components.browser.state.selector.findTab
|
||||||
import mozilla.components.lib.state.Action
|
import mozilla.components.lib.state.Action
|
||||||
import mozilla.components.lib.state.State
|
import mozilla.components.lib.state.State
|
||||||
import mozilla.components.lib.state.Store
|
import mozilla.components.lib.state.Store
|
||||||
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||||
|
import org.mozilla.fenix.components.Components
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
import org.mozilla.fenix.search.ext.areShortcutsAvailable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [Store] for holding the [SearchFragmentState] and applying [SearchFragmentAction]s.
|
* The [Store] for holding the [SearchFragmentState] and applying [SearchFragmentAction]s.
|
||||||
|
@ -66,6 +71,51 @@ data class SearchFragmentState(
|
||||||
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?
|
val searchAccessPoint: Event.PerformedSearch.SearchAccessPoint?
|
||||||
) : State
|
) : State
|
||||||
|
|
||||||
|
fun createInitialSearchFragmentState(
|
||||||
|
activity: HomeActivity,
|
||||||
|
components: Components,
|
||||||
|
tabId: String?,
|
||||||
|
pastedText: String?,
|
||||||
|
searchAccessPoint: Event.PerformedSearch.SearchAccessPoint
|
||||||
|
): SearchFragmentState {
|
||||||
|
val settings = components.settings
|
||||||
|
val tab = tabId?.let { components.core.store.state.findTab(it) }
|
||||||
|
|
||||||
|
val url = tab?.content?.url.orEmpty()
|
||||||
|
val currentSearchEngine = SearchEngineSource.Default(
|
||||||
|
components.search.provider.getDefaultEngine(activity)
|
||||||
|
)
|
||||||
|
|
||||||
|
val browsingMode = activity.browsingModeManager.mode
|
||||||
|
val areShortcutsAvailable = components.search.provider.areShortcutsAvailable(activity)
|
||||||
|
|
||||||
|
val shouldShowSearchSuggestions = when (browsingMode) {
|
||||||
|
BrowsingMode.Normal -> settings.shouldShowSearchSuggestions
|
||||||
|
BrowsingMode.Private ->
|
||||||
|
settings.shouldShowSearchSuggestions && settings.shouldShowSearchSuggestionsInPrivate
|
||||||
|
}
|
||||||
|
|
||||||
|
return SearchFragmentState(
|
||||||
|
query = url,
|
||||||
|
url = url,
|
||||||
|
searchTerms = tab?.content?.searchTerms.orEmpty(),
|
||||||
|
searchEngineSource = currentSearchEngine,
|
||||||
|
defaultEngineSource = currentSearchEngine,
|
||||||
|
showSearchSuggestions = shouldShowSearchSuggestions,
|
||||||
|
showSearchSuggestionsHint = false,
|
||||||
|
showSearchShortcuts = url.isEmpty() &&
|
||||||
|
areShortcutsAvailable &&
|
||||||
|
settings.shouldShowSearchShortcuts,
|
||||||
|
areShortcutsAvailable = areShortcutsAvailable,
|
||||||
|
showClipboardSuggestions = settings.shouldShowClipboardSuggestions,
|
||||||
|
showHistorySuggestions = settings.shouldShowHistorySuggestions,
|
||||||
|
showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions,
|
||||||
|
tabId = tabId,
|
||||||
|
pastedText = pastedText,
|
||||||
|
searchAccessPoint = searchAccessPoint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer.
|
* Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.search.ext
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.mozilla.fenix.components.searchengine.FenixSearchEngineProvider
|
||||||
|
|
||||||
|
private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if the user has *at least 2* installed search engines.
|
||||||
|
* Useful to decide whether to show / enable certain functionalities.
|
||||||
|
*/
|
||||||
|
fun FenixSearchEngineProvider.areShortcutsAvailable(context: Context) =
|
||||||
|
installedSearchEngines(context).list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS
|
|
@ -19,33 +19,22 @@ import androidx.navigation.fragment.navArgs
|
||||||
import kotlinx.android.synthetic.main.fragment_search.view.*
|
import kotlinx.android.synthetic.main.fragment_search.view.*
|
||||||
import kotlinx.android.synthetic.main.fragment_search_dialog.*
|
import kotlinx.android.synthetic.main.fragment_search_dialog.*
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import mozilla.components.browser.state.selector.findTab
|
|
||||||
import mozilla.components.lib.state.ext.consumeFrom
|
import mozilla.components.lib.state.ext.consumeFrom
|
||||||
import mozilla.components.support.base.feature.UserInteractionHandler
|
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
import org.mozilla.fenix.search.SearchEngineSource
|
|
||||||
import org.mozilla.fenix.search.SearchFragmentState
|
|
||||||
import org.mozilla.fenix.search.SearchFragmentStore
|
import org.mozilla.fenix.search.SearchFragmentStore
|
||||||
import org.mozilla.fenix.search.SearchInteractor
|
import org.mozilla.fenix.search.SearchInteractor
|
||||||
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
|
import org.mozilla.fenix.search.awesomebar.AwesomeBarView
|
||||||
|
import org.mozilla.fenix.search.createInitialSearchFragmentState
|
||||||
import org.mozilla.fenix.search.toolbar.ToolbarView
|
import org.mozilla.fenix.search.toolbar.ToolbarView
|
||||||
import org.mozilla.fenix.utils.Settings
|
|
||||||
|
|
||||||
typealias SearchDialogFragmentStore = SearchFragmentStore
|
typealias SearchDialogFragmentStore = SearchFragmentStore
|
||||||
typealias SearchDialogInteractor = SearchInteractor
|
typealias SearchDialogInteractor = SearchInteractor
|
||||||
fun Settings.shouldShowSearchSuggestions(isPrivate: Boolean): Boolean {
|
|
||||||
return if (isPrivate) {
|
|
||||||
shouldShowSearchSuggestions && shouldShowSearchSuggestionsInPrivate
|
|
||||||
} else {
|
|
||||||
shouldShowSearchSuggestions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
||||||
|
|
||||||
|
@ -72,8 +61,18 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
|
val args by navArgs<SearchDialogFragmentArgs>()
|
||||||
val view = inflater.inflate(R.layout.fragment_search_dialog, container, false)
|
val view = inflater.inflate(R.layout.fragment_search_dialog, container, false)
|
||||||
store = SearchDialogFragmentStore(setUpState())
|
|
||||||
|
store = SearchDialogFragmentStore(
|
||||||
|
createInitialSearchFragmentState(
|
||||||
|
activity as HomeActivity,
|
||||||
|
requireComponents,
|
||||||
|
tabId = args.sessionId,
|
||||||
|
pastedText = args.pastedText,
|
||||||
|
searchAccessPoint = args.searchAccessPoint
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
interactor = SearchDialogInteractor(
|
interactor = SearchDialogInteractor(
|
||||||
SearchDialogController(
|
SearchDialogController(
|
||||||
|
@ -146,43 +145,4 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpState(): SearchFragmentState {
|
|
||||||
val activity = activity as HomeActivity
|
|
||||||
val settings = activity.settings()
|
|
||||||
val args by navArgs<SearchDialogFragmentArgs>()
|
|
||||||
val tabId = args.sessionId
|
|
||||||
val tab = tabId?.let { requireComponents.core.store.state.findTab(it) }
|
|
||||||
val url = tab?.content?.url.orEmpty()
|
|
||||||
val currentSearchEngine = SearchEngineSource.Default(
|
|
||||||
requireComponents.search.provider.getDefaultEngine(requireContext())
|
|
||||||
)
|
|
||||||
val isPrivate = activity.browsingModeManager.mode.isPrivate
|
|
||||||
val areShortcutsAvailable =
|
|
||||||
requireContext().components.search.provider.installedSearchEngines(requireContext())
|
|
||||||
.list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS
|
|
||||||
return SearchFragmentState(
|
|
||||||
query = url,
|
|
||||||
url = url,
|
|
||||||
searchTerms = tab?.content?.searchTerms.orEmpty(),
|
|
||||||
searchEngineSource = currentSearchEngine,
|
|
||||||
defaultEngineSource = currentSearchEngine,
|
|
||||||
showSearchSuggestions = settings.shouldShowSearchSuggestions(isPrivate),
|
|
||||||
showSearchSuggestionsHint = false,
|
|
||||||
showSearchShortcuts = settings.shouldShowSearchShortcuts &&
|
|
||||||
url.isEmpty() &&
|
|
||||||
areShortcutsAvailable,
|
|
||||||
areShortcutsAvailable = areShortcutsAvailable,
|
|
||||||
showClipboardSuggestions = settings.shouldShowClipboardSuggestions,
|
|
||||||
showHistorySuggestions = settings.shouldShowHistorySuggestions,
|
|
||||||
showBookmarkSuggestions = settings.shouldShowBookmarkSuggestions,
|
|
||||||
tabId = tabId,
|
|
||||||
pastedText = args.pastedText,
|
|
||||||
searchAccessPoint = args.searchAccessPoint
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue