Adds toolbar with autocomplete and menu to BrowserFragment
parent
6f17107e87
commit
5a3fc1325f
|
@ -70,6 +70,7 @@ dependencies {
|
|||
|
||||
implementation Deps.mozilla_concept_engine
|
||||
implementation Deps.mozilla_concept_storage
|
||||
implementation Deps.mozilla_concept_toolbar
|
||||
|
||||
implementation Deps.mozilla_browser_awesomebar
|
||||
implementation Deps.mozilla_browser_domains
|
||||
|
@ -81,7 +82,7 @@ dependencies {
|
|||
implementation Deps.mozilla_feature_intent
|
||||
implementation Deps.mozilla_feature_session
|
||||
implementation Deps.mozilla_feature_toolbar
|
||||
|
||||
implementation Deps.mozilla_feature_tabs
|
||||
implementation Deps.mozilla_support_ktx
|
||||
|
||||
testImplementation Deps.junit
|
||||
|
|
|
@ -14,6 +14,7 @@ import mozilla.components.feature.session.SessionFeature
|
|||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.toolbar.ToolbarIntegration
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
|
||||
class BrowserFragment : Fragment() {
|
||||
|
@ -41,7 +42,16 @@ class BrowserFragment : Fragment() {
|
|||
sessionFeature = SessionFeature(
|
||||
sessionManager,
|
||||
SessionUseCases(sessionManager),
|
||||
engineView)
|
||||
engineView
|
||||
)
|
||||
|
||||
lifecycle.addObserver(
|
||||
ToolbarIntegration(
|
||||
requireContext(),
|
||||
toolbar,
|
||||
requireComponents.toolbar.shippedDomainsProvider
|
||||
)
|
||||
)
|
||||
|
||||
lifecycle.addObservers(sessionFeature)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package org.mozilla.fenix.components
|
||||
|
||||
import android.content.Context
|
||||
import org.mozilla.fenix.components.toolbar.Toolbar
|
||||
|
||||
/**
|
||||
* Provides access to all components.
|
||||
|
@ -13,4 +14,11 @@ class Components(private val context: Context) {
|
|||
val core by lazy { Core(context) }
|
||||
val search by lazy { Search(context) }
|
||||
val useCases by lazy { UseCases(context, core.sessionManager, search.searchEngineManager) }
|
||||
val toolbar by lazy {
|
||||
Toolbar(
|
||||
context,
|
||||
useCases.sessionUseCases,
|
||||
core.sessionManager
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* 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/. */
|
||||
* 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.components
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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/. */
|
||||
* 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.components
|
||||
|
||||
|
@ -20,8 +20,18 @@ class UseCases(
|
|||
private val sessionManager: SessionManager,
|
||||
private val searchEngineManager: SearchEngineManager
|
||||
) {
|
||||
/**
|
||||
* Use cases that provide engine interactions for a given browser session.
|
||||
*/
|
||||
val sessionUseCases by lazy { SessionUseCases(sessionManager) }
|
||||
|
||||
/**
|
||||
* Use cases that provide tab management.
|
||||
*/
|
||||
val tabsUseCases: TabsUseCases by lazy { TabsUseCases(sessionManager) }
|
||||
|
||||
/**
|
||||
* Use cases that provide search engine integration.
|
||||
*/
|
||||
val searchUseCases by lazy { SearchUseCases(context, searchEngineManager, sessionManager) }
|
||||
val sessionUseCases by lazy { SessionUseCases(sessionManager) };
|
||||
val tabsUseCases by lazy { TabsUseCases(sessionManager) }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* 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.components.toolbar
|
||||
|
||||
import android.content.Context
|
||||
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
|
||||
import mozilla.components.browser.menu.BrowserMenuBuilder
|
||||
import mozilla.components.browser.menu.item.BrowserMenuItemToolbar
|
||||
import mozilla.components.browser.menu.item.BrowserMenuSwitch
|
||||
import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
/**
|
||||
* Component group for all functionality related to the browser toolbar.
|
||||
*/
|
||||
class Toolbar(
|
||||
private val context: Context,
|
||||
private val sessionUseCases: SessionUseCases,
|
||||
private val sessionManager: SessionManager
|
||||
) {
|
||||
|
||||
/**
|
||||
* Helper class for building browser menus.app
|
||||
*/
|
||||
val menuBuilder by lazy { BrowserMenuBuilder(menuItems) }
|
||||
|
||||
/**
|
||||
* Provides autocomplete functionality for shipped / provided domain lists.
|
||||
*/
|
||||
val shippedDomainsProvider by lazy {
|
||||
ShippedDomainsProvider().also { it.initialize(context) }
|
||||
}
|
||||
|
||||
private val menuToolbar by lazy {
|
||||
val back = BrowserMenuItemToolbar.Button(
|
||||
mozilla.components.ui.icons.R.drawable.mozac_ic_back,
|
||||
iconTintColorResource = R.color.icons,
|
||||
contentDescription = "Back"
|
||||
) {
|
||||
sessionUseCases.goBack.invoke()
|
||||
}
|
||||
|
||||
val forward = BrowserMenuItemToolbar.Button(
|
||||
mozilla.components.ui.icons.R.drawable.mozac_ic_forward,
|
||||
iconTintColorResource = R.color.icons,
|
||||
contentDescription = "Forward"
|
||||
) {
|
||||
sessionUseCases.goForward.invoke()
|
||||
}
|
||||
|
||||
val refresh = BrowserMenuItemToolbar.Button(
|
||||
mozilla.components.ui.icons.R.drawable.mozac_ic_refresh,
|
||||
iconTintColorResource = R.color.icons,
|
||||
contentDescription = "Refresh"
|
||||
) {
|
||||
sessionUseCases.reload.invoke()
|
||||
}
|
||||
|
||||
BrowserMenuItemToolbar(listOf(back, forward, refresh))
|
||||
}
|
||||
|
||||
private val menuItems by lazy {
|
||||
listOf(
|
||||
menuToolbar,
|
||||
SimpleBrowserMenuItem(context.getString(R.string.browser_menu_help)) {
|
||||
// TODO Help
|
||||
},
|
||||
|
||||
SimpleBrowserMenuItem(context.getString(R.string.browser_menu_settings)) {
|
||||
openSettingsActivity()
|
||||
},
|
||||
|
||||
SimpleBrowserMenuItem(context.getString(R.string.browser_menu_library)) {
|
||||
// TODO Your Library
|
||||
},
|
||||
|
||||
BrowserMenuSwitch(context.getString(R.string.browser_menu_desktop_site), {
|
||||
sessionManager.selectedSessionOrThrow.desktopMode
|
||||
}) { checked ->
|
||||
sessionUseCases.requestDesktopSite.invoke(checked)
|
||||
}.apply {
|
||||
visible = { sessionManager.selectedSession != null }
|
||||
},
|
||||
|
||||
SimpleBrowserMenuItem(context.getString(R.string.browser_menu_find_in_page)) {
|
||||
// TODO Find in Page
|
||||
},
|
||||
|
||||
SimpleBrowserMenuItem(context.getString(R.string.browser_menu_private_tab)) {
|
||||
// TODO Private Tab
|
||||
},
|
||||
|
||||
SimpleBrowserMenuItem(context.getString(R.string.browser_menu_new_tab)) {
|
||||
// TODO New Tab
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun openSettingsActivity() {
|
||||
// TODO Open Settings
|
||||
}
|
||||
}
|
|
@ -5,13 +5,18 @@
|
|||
package org.mozilla.fenix.components.toolbar
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.FragmentNavigator
|
||||
import mozilla.components.browser.domains.autocomplete.DomainAutocompleteProvider
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.feature.toolbar.ToolbarAutocompleteFeature
|
||||
import mozilla.components.feature.toolbar.ToolbarFeature
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.application
|
||||
import org.mozilla.fenix.ext.components
|
||||
|
||||
class ToolbarIntegration(
|
||||
|
@ -21,6 +26,29 @@ class ToolbarIntegration(
|
|||
sessionId: String? = null
|
||||
) : LifecycleObserver {
|
||||
init {
|
||||
toolbar.setMenuBuilder(context.components.toolbar.menuBuilder)
|
||||
|
||||
val home = BrowserToolbar.Button(
|
||||
context.resources.getDrawable(
|
||||
R.drawable.ic_home,
|
||||
context.application.theme
|
||||
),
|
||||
"Home"
|
||||
) {
|
||||
Navigation.findNavController(toolbar).navigate(R.id.action_browserFragment_to_homeFragment)
|
||||
}
|
||||
|
||||
toolbar.addBrowserAction(home)
|
||||
|
||||
toolbar.onUrlClicked = {
|
||||
val extras = FragmentNavigator.Extras.Builder().addSharedElement(
|
||||
toolbar, ViewCompat.getTransitionName(toolbar)!!
|
||||
).build()
|
||||
Navigation.findNavController(toolbar)
|
||||
.navigate(R.id.action_browserFragment_to_searchFragment, null, null, extras)
|
||||
false
|
||||
}
|
||||
|
||||
ToolbarAutocompleteFeature(toolbar).apply {
|
||||
addDomainProvider(domainAutocompleteProvider)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,59 @@
|
|||
/* 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/. */
|
||||
* 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.ext
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.*
|
||||
import androidx.annotation.StringRes
|
||||
import mozilla.components.support.base.log.Log
|
||||
import mozilla.components.support.base.log.Log.Priority.WARN
|
||||
import org.mozilla.fenix.FenixApplication
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.Components
|
||||
|
||||
/**
|
||||
* Get the BrowserApplication object from a context.
|
||||
*/
|
||||
val Context.application: FenixApplication
|
||||
get() = applicationContext as FenixApplication
|
||||
|
||||
/**
|
||||
* Get the requireComponents of this application.
|
||||
*/
|
||||
val Context.components: Components
|
||||
get() = application.components
|
||||
get() = application.components
|
||||
|
||||
fun Context.getPreferenceKey(@StringRes resourceId: Int): String =
|
||||
resources.getString(resourceId)
|
||||
|
||||
/**
|
||||
* Shares content via [ACTION_SEND] intent.
|
||||
*
|
||||
* @param text the data to be shared [EXTRA_TEXT]
|
||||
* @param subject of the intent [EXTRA_TEXT]
|
||||
* @return true it is able to share false otherwise.
|
||||
*/
|
||||
fun Context.share(text: String, subject: String = ""): Boolean {
|
||||
return try {
|
||||
val intent = Intent(ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(EXTRA_SUBJECT, subject)
|
||||
putExtra(EXTRA_TEXT, text)
|
||||
flags = FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
|
||||
val shareIntent = Intent.createChooser(intent, getString(R.string.menu_share_with)).apply {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
|
||||
startActivity(shareIntent)
|
||||
true
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.log(WARN, message = "No activity to share to found", throwable = e, tag = "Reference-Browser")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/* 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/. */
|
||||
* 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.ext
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.mozilla.fenix.components.Components
|
||||
|
||||
val Fragment.requireComponents: Components
|
||||
/**
|
||||
* Get the requireComponents of this application.
|
||||
*/
|
||||
val androidx.fragment.app.Fragment.requireComponents: Components
|
||||
get() = requireContext().components
|
File diff suppressed because one or more lines are too long
|
@ -36,7 +36,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@android:color/white"
|
||||
android:background="@color/colorPrimary"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
|
|
|
@ -17,5 +17,12 @@
|
|||
</fragment>
|
||||
|
||||
<fragment android:id="@+id/browserFragment" android:name="org.mozilla.fenix.browser.BrowserFragment"
|
||||
android:label="fragment_browser" tools:layout="@layout/fragment_browser"/>
|
||||
android:label="fragment_browser" tools:layout="@layout/fragment_browser">
|
||||
<action
|
||||
android:id="@+id/action_browserFragment_to_homeFragment"
|
||||
app:destination="@id/homeFragment" />
|
||||
<action
|
||||
android:id="@+id/action_browserFragment_to_searchFragment"
|
||||
app:destination="@id/searchFragment" />
|
||||
</fragment>
|
||||
</navigation>
|
|
@ -9,4 +9,6 @@
|
|||
|
||||
<color name="searchStroke">#331b215e</color>
|
||||
<color name="searchText">#0C0C0D</color>
|
||||
<color name="offwhite">#f9f9fa</color>
|
||||
<color name="icons">#0C0C0D</color>
|
||||
</resources>
|
||||
|
|
|
@ -6,4 +6,13 @@
|
|||
<string name="app_name">Fenix</string>
|
||||
|
||||
<string name="search_hint">Search the Web or enter address</string>
|
||||
<string name="menu_share_with">Share with…</string>
|
||||
<string name="browser_menu_help">Help</string>
|
||||
<string name="browser_menu_settings">Settings</string>
|
||||
<string name="browser_menu_library">Your Library</string>
|
||||
<string name="browser_menu_desktop_site">Desktop Site</string>
|
||||
<string name="browser_menu_find_in_page">Find in Page</string>
|
||||
<string name="browser_menu_private_tab">Private Tab</string>
|
||||
<string name="browser_menu_new_tab">New Tab</string>
|
||||
<string name="browser_menu_report_issue">Report Issue</string>
|
||||
</resources>
|
||||
|
|
|
@ -33,18 +33,32 @@ object Deps {
|
|||
const val androidx_constraintlayout = "androidx.constraintlayout:constraintlayout:${Versions.androidx_constraint_layout}"
|
||||
|
||||
const val mozilla_concept_engine = "org.mozilla.components:concept-engine:${Versions.mozilla_android_components}"
|
||||
const val mozilla_concept_tabstray = "org.mozilla.components:concept-tabstray:${Versions.mozilla_android_components}"
|
||||
const val mozilla_concept_toolbar = "org.mozilla.components:concept-toolbar:${Versions.mozilla_android_components}"
|
||||
const val mozilla_concept_storage = "org.mozilla.components:concept-storage:${Versions.mozilla_android_components}"
|
||||
|
||||
const val mozilla_browser_awesomebar = "org.mozilla.components:browser-awesomebar:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_domains = "org.mozilla.components:browser-domains:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_engine_gecko_nightly = "org.mozilla.components:browser-engine-gecko-nightly:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_domains = "org.mozilla.components:browser-domains:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_search = "org.mozilla.components:browser-search:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_session = "org.mozilla.components:browser-session:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_tabstray = "org.mozilla.components:browser-tabstray:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_toolbar = "org.mozilla.components:browser-toolbar:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_menu = "org.mozilla.components:browser-menu:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_errorpages = "org.mozilla.components:browser-errorpages:${Versions.mozilla_android_components}"
|
||||
const val mozilla_browser_storage_sync = "org.mozilla.components:browser-storage-sync:${Versions.mozilla_android_components}"
|
||||
|
||||
const val mozilla_feature_awesomebar = "org.mozilla.components:feature-awesomebar:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_contextmenu = "org.mozilla.components:feature-contextmenu:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_customtabs = "org.mozilla.components:feature-customtabs:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_intent = "org.mozilla.components:feature-intent:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_search = "org.mozilla.components:feature-search:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_session = "org.mozilla.components:feature-session:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_sync = "org.mozilla.components:feature-sync:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_tabs = "org.mozilla.components:feature-tabs:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_downloads = "org.mozilla.components:feature-downloads:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_storage = "org.mozilla.components:feature-storage:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_prompts = "org.mozilla.components:feature-prompts:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_toolbar = "org.mozilla.components:feature-toolbar:${Versions.mozilla_android_components}"
|
||||
|
||||
const val mozilla_support_ktx = "org.mozilla.components:support-ktx:${Versions.mozilla_android_components}"
|
||||
|
|
Loading…
Reference in New Issue