Issue #45: Use fragments and add tabs tray component.

Sebastian Kaspari 6 years ago committed by Christian Sadilek
parent e3da924944
commit b6ce863e6f

@ -146,12 +146,14 @@ dependencies {
implementation "org.mozilla.components:engine:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:search:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:session:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:tabstray:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:abstract-toolbar:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:toolbar:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.photon:icons:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:feature-search:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:feature-session:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:feature-tabs:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:feature-toolbar:${rootProject.ext.dependencies['mozillaComponents']}"
implementation "org.mozilla.components:autocomplete:${rootProject.ext.dependencies['mozillaComponents']}"
@ -177,6 +179,8 @@ dependencies {
productionAarch64Implementation "org.mozilla:geckoview-release-arm64-v8a:${rootProject.ext.geckoRelease['version']}"
implementation "com.android.support:appcompat-v7:${rootProject.ext.dependencies['supportLibraries']}"
implementation "com.android.support.constraint:constraint-layout:1.1.2"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${rootProject.ext.dependencies['kotlin']}"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${rootProject.ext.dependencies['coroutines']}"
implementation "com.android.support.constraint:constraint-layout:${rootProject.ext.dependencies['constraintLayout']}"

@ -9,53 +9,40 @@ import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.AttributeSet
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
import mozilla.components.browser.tabstray.BrowserTabsTray
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.session.SessionFeature
import mozilla.components.feature.toolbar.ToolbarFeature
import mozilla.fenix.components.FeatureLifecycleObserver
import mozilla.components.concept.tabstray.TabsTray
import mozilla.fenix.ext.components
import mozilla.fenix.fragment.BackHandler
import mozilla.fenix.fragment.BrowserFragment
class MainActivity : AppCompatActivity() {
private lateinit var toolbarFeature: ToolbarFeature
private lateinit var sessionFeature: SessionFeature
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
toolbar.setMenuBuilder(components.menuBuilder)
toolbarFeature = ToolbarFeature(
toolbar,
components.sessionManager,
components.sessionUseCases.loadUrl,
components.defaultSearchUseCase)
sessionFeature = SessionFeature(
components.sessionManager,
components.sessionUseCases,
engineView,
components.sessionStorage)
lifecycle.addObserver(FeatureLifecycleObserver(sessionFeature, toolbarFeature))
if (savedInstanceState == null) {
supportFragmentManager?.beginTransaction()?.apply {
replace(R.id.container, BrowserFragment.create())
commit()
}
}
}
override fun onBackPressed() {
if (toolbarFeature.handleBackPressed())
return
if (sessionFeature.handleBackPressed())
return
supportFragmentManager.fragments.forEach {
if (it is BackHandler && it.onBackPressed()) {
return
}
}
super.onBackPressed()
}
override fun onCreateView(parent: View?, name: String?, context: Context?, attrs: AttributeSet?): View? {
if (name == EngineView::class.java.name) {
return components.engine.createView(context!!, attrs).asView()
override fun onCreateView(parent: View?, name: String?, context: Context, attrs: AttributeSet?): View? =
when (name) {
EngineView::class.java.name -> components.engine.createView(context, attrs).asView()
TabsTray::class.java.name -> BrowserTabsTray(context, attrs)
else -> super.onCreateView(parent, name, context, attrs)
}
return super.onCreateView(parent, name, context, attrs)
}
}

@ -16,6 +16,7 @@ import mozilla.components.browser.session.storage.DefaultSessionStorage
import mozilla.components.concept.engine.Engine
import mozilla.components.feature.search.SearchUseCases
import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.fenix.R
import org.mozilla.geckoview.GeckoRuntime
@ -79,4 +80,7 @@ class Components(private val applicationContext: Context) {
BrowserMenuItemToolbar(listOf(forward, refresh))
}
// Tabs
val tabsUseCases: TabsUseCases by lazy { TabsUseCases(sessionManager) }
}

@ -0,0 +1,14 @@
/* 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 mozilla.fenix.ext
import android.support.v4.app.Fragment
import mozilla.fenix.components.Components
/**
* Get the components of this application.
*/
val Fragment.components: Components
get() = activity!!.components

@ -0,0 +1,12 @@
/* 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 mozilla.fenix.fragment
/**
* Interface for fragments that want to handle 'back' button presses.
*/
interface BackHandler {
fun onBackPressed(): Boolean
}

@ -0,0 +1,97 @@
/* 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 mozilla.fenix.fragment
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_browser.*
import mozilla.components.feature.session.SessionFeature
import mozilla.components.feature.tabs.toolbar.TabsToolbarFeature
import mozilla.components.feature.toolbar.ToolbarFeature
import mozilla.fenix.ext.components
import mozilla.fenix.R
class BrowserFragment : Fragment(), BackHandler {
private lateinit var sessionFeature: SessionFeature
private lateinit var toolbarFeature: ToolbarFeature
private lateinit var tabsToolbarFeature: TabsToolbarFeature
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_browser, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar.setMenuBuilder(components.menuBuilder)
val sessionId = arguments?.getString(SESSION_ID)
sessionFeature = SessionFeature(
components.sessionManager,
components.sessionUseCases,
engineView,
components.sessionStorage,
sessionId)
toolbarFeature = ToolbarFeature(
toolbar,
components.sessionManager,
components.sessionUseCases.loadUrl,
components.defaultSearchUseCase,
sessionId)
tabsToolbarFeature = TabsToolbarFeature(context!!, toolbar, ::showTabs)
}
private fun showTabs() {
// For now we are performing manual fragment transactions here. Once we can use the new
// navigation support library we may want to pass navigation graphs around.
activity?.supportFragmentManager?.beginTransaction()?.apply {
replace(R.id.container, TabsTrayFragment())
commit()
}
}
override fun onStart() {
super.onStart()
sessionFeature.start()
toolbarFeature.start()
}
override fun onStop() {
super.onStop()
sessionFeature.stop()
toolbarFeature.stop()
}
@Suppress("ReturnCount")
override fun onBackPressed(): Boolean {
if (toolbarFeature.handleBackPressed()) {
return true
}
if (sessionFeature.handleBackPressed()) {
return true
}
return false
}
companion object {
private const val SESSION_ID = "session_id"
fun create(sessionId: String? = null): BrowserFragment = BrowserFragment().apply {
arguments = Bundle().apply {
putString(SESSION_ID, sessionId)
}
}
}
}

@ -0,0 +1,71 @@
/* 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 mozilla.fenix.fragment
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_tabstray.*
import mozilla.components.feature.tabs.tabstray.TabsFeature
import mozilla.fenix.R
import mozilla.fenix.ext.components
/**
* A fragment for displaying the tabs tray.
*/
class TabsTrayFragment : Fragment(), BackHandler {
private var tabsFeature: TabsFeature? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(R.layout.fragment_tabstray, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar.setNavigationIcon(R.drawable.mozac_ic_back)
toolbar.setNavigationOnClickListener {
closeTabsTray()
}
toolbar.inflateMenu(R.menu.menu_tabstray)
toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.newTab -> {
components.tabsUseCases.addSession.invoke("about:blank", selectTab = true)
closeTabsTray()
}
}
true
}
tabsFeature = TabsFeature(tabsTray, components.sessionManager, components.tabsUseCases, ::closeTabsTray)
}
override fun onStart() {
super.onStart()
tabsFeature?.start()
}
override fun onStop() {
super.onStop()
tabsFeature?.stop()
}
override fun onBackPressed(): Boolean {
closeTabsTray()
return true
}
private fun closeTabsTray() {
activity?.supportFragmentManager?.beginTransaction()?.apply {
replace(R.id.container, BrowserFragment.create())
commit()
}
}
}

@ -2,23 +2,9 @@
<!-- 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/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<mozilla.components.browser.toolbar.BrowserToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary" />
<mozilla.components.concept.engine.EngineView
android:id="@+id/engineView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
tools:ignore="MergeRootFrame" />

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<mozilla.components.browser.toolbar.BrowserToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@color/colorPrimary" />
<mozilla.components.concept.engine.EngineView
android:id="@+id/engineView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@color/colorPrimary" />
<mozilla.components.concept.tabstray.TabsTray
android:id="@+id/tabsTray"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar">
</mozilla.components.concept.tabstray.TabsTray>
</android.support.constraint.ConstraintLayout>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/newTab"
android:icon="@drawable/mozac_ic_tab_new"
android:title="@string/menu_action_add_tab"
app:showAsAction="ifRoom" />
</menu>

@ -4,4 +4,6 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
<string name="app_name">Fenix</string>
<string name="menu_action_add_tab">Add New Tab</string>
</resources>

Loading…
Cancel
Save