1
0
Fork 0

Adds toolbar with autocomplete and menu to BrowserFragment

master
Emily Kager 2019-01-23 14:48:15 -08:00 committed by Jeff Boek
parent 6f17107e87
commit 5a3fc1325f
15 changed files with 274 additions and 18 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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
)
}
}

View File

@ -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

View File

@ -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) }
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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}"