diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 12bd9080d..b20a8d2ad 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -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() .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) } diff --git a/app/src/main/java/org/mozilla/fenix/home/tabs/TabsComponent.kt b/app/src/main/java/org/mozilla/fenix/home/tabs/TabsComponent.kt index 3d48e1305..e69df8ea3 100644 --- a/app/src/main/java/org/mozilla/fenix/home/tabs/TabsComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/home/tabs/TabsComponent.kt @@ -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( @@ -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() } diff --git a/app/src/main/java/org/mozilla/fenix/home/tabs/TabsUIView.kt b/app/src/main/java/org/mozilla/fenix/home/tabs/TabsUIView.kt index dc818a89c..ee2597ff8 100644 --- a/app/src/main/java/org/mozilla/fenix/home/tabs/TabsUIView.kt +++ b/app/src/main/java/org/mozilla/fenix/home/tabs/TabsUIView.kt @@ -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, - isPrivate: Boolean, changesObservable: Observable ) : UIView(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 { 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 { diff --git a/app/src/main/res/drawable/delete_history_background.xml b/app/src/main/res/drawable/button_background.xml similarity index 100% rename from app/src/main/res/drawable/delete_history_background.xml rename to app/src/main/res/drawable/button_background.xml diff --git a/app/src/main/res/layout/component_tabs.xml b/app/src/main/res/layout/component_tabs.xml index 1ad5dd5ce..e73f787bc 100644 --- a/app/src/main/res/layout/component_tabs.xml +++ b/app/src/main/res/layout/component_tabs.xml @@ -1,8 +1,82 @@ - + \ No newline at end of file + xmlns:app="http://schemas.android.com/apk/res-auto"> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/history_delete.xml b/app/src/main/res/layout/history_delete.xml index 5cf27420e..9e82722ba 100644 --- a/app/src/main/res/layout/history_delete.xml +++ b/app/src/main/res/layout/history_delete.xml @@ -5,7 +5,7 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4f43a09f6..c0b5cdb78 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -165,6 +165,10 @@ people before profit. Our mission: keep the Internet open and accessible to all. Current session image + + + Save Session + Delete