1
0
Fork 0

For #633 - Gives the user the ability to save their session

master
Jeff Boek 2019-02-27 13:29:19 -08:00
parent 46789f4c62
commit 416382c3ad
8 changed files with 139 additions and 81 deletions

View File

@ -23,6 +23,7 @@ import kotlinx.android.synthetic.main.fragment_home.view.*
import mozilla.components.browser.menu.BrowserMenu
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.feature.session.bundling.SessionBundleStorage
import org.mozilla.fenix.BrowsingModeManager
import org.mozilla.fenix.DefaultThemeManager
import org.mozilla.fenix.HomeActivity
@ -42,6 +43,12 @@ import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter
import kotlin.math.roundToInt
fun SessionBundleStorage.archive(sessionManager: SessionManager) {
save(sessionManager.createSnapshot())
sessionManager.removeAll()
new()
}
class HomeFragment : Fragment() {
private val bus = ActionBusFactory.get(this)
private var sessionObserver: SessionManager.Observer? = null
@ -56,7 +63,9 @@ class HomeFragment : Fragment() {
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
val sessionManager = requireComponents.core.sessionManager
tabsComponent = TabsComponent(view.homeContainer, bus, (activity as HomeActivity).browsingModeManager.isPrivate,
tabsComponent = TabsComponent(
view.homeContainer,
bus,
TabsState(sessionManager.sessions.map { it.toSessionViewState(it == sessionManager.selectedSession) })
)
sessionsComponent = SessionsComponent(view.homeContainer, bus)
@ -76,7 +85,7 @@ class HomeFragment : Fragment() {
sessionsComponent.view.visibility = if ((activity as HomeActivity).browsingModeManager.isPrivate)
View.GONE else View.VISIBLE
tabsComponent.view.isNestedScrollingEnabled = false
tabsComponent.tabList.isNestedScrollingEnabled = false
sessionsComponent.view.isNestedScrollingEnabled = false
val bundles = requireComponents.core.sessionStorage.bundles(temporaryNumberOfSessions)
@ -159,6 +168,9 @@ class HomeFragment : Fragment() {
getAutoDisposeObservable<TabsAction>()
.subscribe {
when (it) {
is TabsAction.Archive -> {
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
}
is TabsAction.Select -> {
val session = requireComponents.core.sessionManager.findSessionById(it.sessionId)
requireComponents.core.sessionManager.select(session!!)
@ -177,6 +189,7 @@ class HomeFragment : Fragment() {
.subscribe {
when (it) {
is SessionsAction.Select -> {
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
it.archivedSession.bundle.restoreSnapshot(requireComponents.core.engine)?.apply {
requireComponents.core.sessionManager.restore(this)
}

View File

@ -6,6 +6,7 @@ package org.mozilla.fenix.home.tabs
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.component_tabs.view.*
import mozilla.components.browser.session.Session
import org.mozilla.fenix.mvi.Action
import org.mozilla.fenix.mvi.ActionBusFactory
@ -16,7 +17,6 @@ import org.mozilla.fenix.mvi.ViewState
class TabsComponent(
private val container: ViewGroup,
bus: ActionBusFactory,
private val isPrivate: Boolean,
override var initialState: TabsState = TabsState(listOf())
) :
UIComponent<TabsState, TabsAction, TabsChange>(
@ -30,9 +30,9 @@ class TabsComponent(
}
}
override fun initView() = TabsUIView(container, actionEmitter, isPrivate, changesObservable)
val view: RecyclerView
get() = uiView.view as RecyclerView
override fun initView() = TabsUIView(container, actionEmitter, changesObservable)
val tabList: RecyclerView
get() = uiView.view.tabs_list as RecyclerView
init {
render(reducer)
@ -47,6 +47,7 @@ fun Session.toSessionViewState(selected: Boolean): SessionViewState {
}
sealed class TabsAction : Action {
object Archive : TabsAction()
data class Select(val sessionId: String) : TabsAction()
data class Close(val sessionId: String) : TabsAction()
}

View File

@ -8,16 +8,15 @@ import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.navigation.Navigation
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.tab_list_header.view.*
import kotlinx.android.synthetic.main.component_tabs.view.*
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.home.HomeFragment
@ -28,46 +27,57 @@ import org.mozilla.fenix.mvi.UIView
class TabsUIView(
container: ViewGroup,
actionEmitter: Observer<TabsAction>,
isPrivate: Boolean,
changesObservable: Observable<TabsChange>
) :
UIView<TabsState, TabsAction, TabsChange>(container, actionEmitter, changesObservable) {
private val header: ConstraintLayout = LayoutInflater.from(container.context)
.inflate(R.layout.tab_list_header, container, true)
.findViewById(R.id.tabs_header)
override val view: RecyclerView = LayoutInflater.from(container.context)
override val view: View = LayoutInflater.from(container.context)
.inflate(R.layout.component_tabs, container, true)
.findViewById(R.id.tabs_list)
private val tabsAdapter = TabsAdapter(actionEmitter)
init {
view.apply {
view.tabs_list.apply {
layoutManager = LinearLayoutManager(container.context)
adapter = tabsAdapter
itemAnimator = DefaultItemAnimator()
}
header.add_tab_button.increaseTapArea(HomeFragment.addTabButtonIncreaseDps)
header.add_tab_button.setOnClickListener {
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null)
Navigation.findNavController(it).navigate(directions)
}
header.tabs_overflow_button.increaseTapArea(HomeFragment.overflowButtonIncreaseDps)
header.tabs_overflow_button.setOnClickListener {
if (view.context as? Activity != null) {
CurrentSessionBottomSheetFragment().show(
(view.context as FragmentActivity).supportFragmentManager,
overflowFragmentTag
)
view.apply {
add_tab_button.increaseTapArea(HomeFragment.addTabButtonIncreaseDps)
add_tab_button.setOnClickListener {
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null)
Navigation.findNavController(it).navigate(directions)
}
tabs_overflow_button.increaseTapArea(HomeFragment.overflowButtonIncreaseDps)
tabs_overflow_button.setOnClickListener {
if (view.context as? Activity != null) {
CurrentSessionBottomSheetFragment().show(
(view.context as FragmentActivity).supportFragmentManager,
overflowFragmentTag
)
}
}
save_session_button_text.apply {
val color = ContextCompat.getColor(context, R.color.photonWhite)
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_archive)
drawable?.setTint(color)
this.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
}
save_session_button.setOnClickListener {
actionEmitter.onNext(TabsAction.Archive)
}
}
}
override fun updateView() = Consumer<TabsState> {
tabsAdapter.sessions = it.sessions
header.visibility = if (it.sessions.isEmpty()) View.GONE else View.VISIBLE
(if (it.sessions.isEmpty()) View.GONE else View.VISIBLE).also { visibility ->
view.tabs_header.visibility = visibility
view.save_session_button.visibility = visibility
}
}
companion object {

View File

@ -1,8 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
<!-- 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/. -->
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tabs_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"/>
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/tabs_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:visibility="gone">
<TextView
android:id="@+id/header_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/tabs_header_title"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textColor="?attr/toolbarTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/add_tab_button"
android:layout_width="@dimen/glyph_button_width"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_new"
android:tint="?attr/toolbarTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tabs_overflow_button"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/tabs_overflow_button"
android:layout_width="@dimen/glyph_button_width"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_menu"
android:tint="?attr/toolbarTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tabs_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"/>
<FrameLayout
android:id="@+id/save_session_button"
android:foreground="?android:attr/selectableItemBackground"
android:background="@drawable/button_background"
android:backgroundTint="@color/photonInk70"
android:layout_margin="16dp"
android:padding="6dp"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/save_session_button_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/session_save"
android:textColor="@color/photonWhite"
android:drawableStart="@drawable/ic_archive"
android:drawablePadding="8dp"
android:textSize="16sp"
android:gravity="center"
android:clickable="false"
android:focusable="false"
android:layout_gravity="center" />
</FrameLayout>
</merge>

View File

@ -5,7 +5,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/delete_history_button"
android:foreground="?android:attr/selectableItemBackground"
android:background="@drawable/delete_history_background"
android:background="@drawable/button_background"
android:layout_margin="16dp"
android:padding="6dp"
android:clickable="true"

View File

@ -1,44 +0,0 @@
<?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/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/tabs_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp">
<TextView
android:id="@+id/header_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/tabs_header_title"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textColor="?attr/toolbarTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/add_tab_button"
android:layout_width="@dimen/glyph_button_width"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_new"
android:tint="?attr/toolbarTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tabs_overflow_button"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/tabs_overflow_button"
android:layout_width="@dimen/glyph_button_width"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_menu"
android:tint="?attr/toolbarTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -165,6 +165,10 @@ people before profit. Our mission: keep the Internet open and accessible to all.
<!-- Content description (not visible, for screen readers etc.): Title icon for current session menu -->
<string name="current_session_image">Current session image</string>
<!-- Text for the button to save a session -->
<string name="session_save">Save Session</string>
<!-- Text for the button to delete a single session -->
<string name="session_item_delete">Delete</string>