1
0
Fork 0

Fixes #354: Overflow menu for multitasking in current session

master
Colin Lee 2019-02-10 19:30:37 -06:00
parent 06890d0837
commit ee229c9709
16 changed files with 309 additions and 93 deletions

View File

@ -25,6 +25,8 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
debug { debug {
shrinkResources false
minifyEnabled false
applicationIdSuffix ".debug" applicationIdSuffix ".debug"
} }
} }

View File

@ -17,14 +17,12 @@ import androidx.fragment.app.Fragment
import androidx.navigation.Navigation import androidx.navigation.Navigation
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_home.view.* import kotlinx.android.synthetic.main.fragment_home.view.*
import kotlinx.android.synthetic.main.tab_list_header.view.*
import mozilla.components.browser.menu.BrowserMenu import mozilla.components.browser.menu.BrowserMenu
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import org.mozilla.fenix.DefaultThemeManager import org.mozilla.fenix.DefaultThemeManager
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.ThemeManager import org.mozilla.fenix.ThemeManager
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.home.sessions.SessionsComponent import org.mozilla.fenix.home.sessions.SessionsComponent
@ -92,12 +90,7 @@ class HomeFragment : Fragment() {
view.toolbar.setCompoundDrawablesWithIntrinsicBounds(searchIcon, null, null, null) view.toolbar.setCompoundDrawablesWithIntrinsicBounds(searchIcon, null, null, null)
val roundToInt = (toolbarPaddingDp * Resources.getSystem().displayMetrics.density).roundToInt() val roundToInt = (toolbarPaddingDp * Resources.getSystem().displayMetrics.density).roundToInt()
view.toolbar.compoundDrawablePadding = roundToInt view.toolbar.compoundDrawablePadding = roundToInt
view.toolbar.setOnClickListener { it -> view.toolbar.setOnClickListener {
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null)
Navigation.findNavController(it).navigate(directions)
}
view.add_tab_button.increaseTapArea(addTabButtonIncreaseDps)
view.add_tab_button.setOnClickListener {
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null) val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null)
Navigation.findNavController(it).navigate(directions) Navigation.findNavController(it).navigate(directions)
} }
@ -210,6 +203,7 @@ class HomeFragment : Fragment() {
companion object { companion object {
const val addTabButtonIncreaseDps = 8 const val addTabButtonIncreaseDps = 8
const val overflowButtonIncreaseDps = 8
const val toolbarPaddingDp = 12f const val toolbarPaddingDp = 12f
const val firstKeyTriggerFrame = 55 const val firstKeyTriggerFrame = 55
const val secondKeyTriggerFrame = 90 const val secondKeyTriggerFrame = 90

View File

@ -0,0 +1,44 @@
/* 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.home.sessions
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.current_session_bottom_sheet.view.*
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.requireComponents
class CurrentSessionBottomSheetFragment : BottomSheetDialogFragment(), LayoutContainer {
override val containerView: View?
get() = view
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(BottomSheetDialogFragment.STYLE_NORMAL, R.style.CurrentSessionBottomSheetDialogTheme)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.current_session_bottom_sheet, container, false)
view.current_session_card_tab_list.text = requireComponents.core.sessionManager.sessions.joinToString(", ") {
if (it.title.length > maxTitleLength) it.title.substring(0, maxTitleLength) + "..." else it.title
}
view.delete_session_button.setOnClickListener {
requireComponents.core.sessionManager.removeAll()
dismiss()
}
return view
}
companion object {
const val maxTitleLength = 20
}
}

View File

@ -4,17 +4,25 @@
package org.mozilla.fenix.home.tabs package org.mozilla.fenix.home.tabs
import android.app.Activity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.FragmentActivity
import androidx.navigation.Navigation
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.functions.Consumer import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.tab_list_header.view.*
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.home.HomeFragment
import org.mozilla.fenix.home.HomeFragmentDirections
import org.mozilla.fenix.home.sessions.CurrentSessionBottomSheetFragment
import org.mozilla.fenix.mvi.UIView import org.mozilla.fenix.mvi.UIView
class TabsUIView( class TabsUIView(
@ -40,10 +48,28 @@ class TabsUIView(
adapter = tabsAdapter adapter = tabsAdapter
itemAnimator = DefaultItemAnimator() 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
)
}
}
} }
override fun updateView() = Consumer<TabsState> { override fun updateView() = Consumer<TabsState> {
tabsAdapter.sessions = it.sessions tabsAdapter.sessions = it.sessions
header.visibility = if (it.sessions.isEmpty()) View.GONE else View.VISIBLE header.visibility = if (it.sessions.isEmpty()) View.GONE else View.VISIBLE
} }
companion object {
const val overflowFragmentTag = "current session overflow"
}
} }

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M11.293,2.293c0.39,-0.39 1.024,-0.39 1.414,0l6,6c0.379,0.392 0.374,1.016 -0.012,1.402 -0.386,0.385 -1.01,0.39 -1.402,0.012L13,5.414V17c0,0.552 -0.448,1 -1,1s-1,-0.448 -1,-1V5.414L6.707,9.707c-0.392,0.379 -1.016,0.373 -1.402,-0.012 -0.386,-0.386 -0.391,-1.01 -0.012,-1.402l6,-6zM3,17c0,-0.552 0.448,-1 1,-1s1,0.448 1,1v2c0,0.552 0.448,1 1,1h13c0.552,0 1,-0.448 1,-1v-2c0,-0.552 0.448,-1 1,-1s1,0.448 1,1v2c0,1.657 -1.343,3 -3,3H6c-1.657,0 -3,-1.343 -3,-3v-2z"
android:fillColor="#202340"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="64"
android:viewportHeight="64">
<path
android:pathData="M12,8L60,8A4,4 0,0 1,64 12L64,60A4,4 0,0 1,60 64L12,64A4,4 0,0 1,8 60L8,12A4,4 0,0 1,12 8z"
android:fillColor="#024690"/>
<path
android:pathData="M8,4L56,4A4,4 0,0 1,60 8L60,56A4,4 0,0 1,56 60L8,60A4,4 0,0 1,4 56L4,8A4,4 0,0 1,8 4z"
android:fillColor="#0B68CD"/>
<path
android:pathData="M4,0L52,0A4,4 0,0 1,56 4L56,52A4,4 0,0 1,52 56L4,56A4,4 0,0 1,0 52L0,4A4,4 0,0 1,4 0z"
android:fillColor="#0390ED"/>
<path
android:pathData="M28.37,22.793L33.5,14 44,32L32.988,32c-0.26,5.567 -4.857,10 -10.488,10C16.701,42 12,37.299 12,31.5S16.701,21 22.5,21c2.175,0 4.195,0.661 5.87,1.793zM28.37,22.793L23,32h9.988c0.008,-0.166 0.012,-0.332 0.012,-0.5 0,-3.624 -1.836,-6.82 -4.63,-8.707z"
android:strokeAlpha="0.5"
android:fillColor="#024690"
android:fillAlpha="0.5"/>
</vector>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
app:layout_behavior="@string/bottom_sheet_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="@+id/current_session_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:cardCornerRadius="10dp"
android:padding="10dp"
android:elevation="5dp"
android:background="?android:attr/colorBackground"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/current_session_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:paddingBottom="20dp"
android:src="@drawable/ic_session_thumbnail_placeholder_blue"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:contentDescription="@string/current_session_image"/>
<TextView
android:id="@+id/current_session_card_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="@string/tabs_header_title"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/current_session_image"
/>
<TextView
android:id="@+id/current_session_card_tab_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@id/current_session_card_title"
app:layout_constraintStart_toEndOf="@id/current_session_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp"
tools:text="@tools:sample/lorem/random"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/delete_session_button"
android:padding="12dp"
android:text="@string/current_session_delete"
android:textSize="18sp"
android:textColor="@color/photonRed60"
android:background="?android:attr/colorBackground"
android:drawableStart="@drawable/ic_delete"
android:drawablePadding="10dp"
android:drawableTint="@color/photonRed60" tools:targetApi="m"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/archive_session_button"
android:padding="12dp"
android:text="@string/current_session_archive"
android:textSize="18sp"
android:background="?android:attr/colorBackground"
android:drawableStart="@drawable/ic_archive"
android:drawablePadding="10dp"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/send_and_share_session_button"
android:padding="12dp"
android:text="@string/current_session_send_and_share"
android:textSize="18sp"
android:background="?android:attr/colorBackground"
android:drawableStart="@drawable/ic_send"
android:drawablePadding="10dp"/>
</LinearLayout>

View File

@ -2,79 +2,83 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- 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 - 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/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/homeLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="?attr/homeBackgroundGradient" <androidx.constraintlayout.motion.widget.MotionLayout
app:layoutDescription="@xml/home_scene" android:id="@+id/homeLayout"
tools:context=".home.HomeFragment"> android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/homeBackgroundGradient"
app:layoutDescription="@xml/home_scene"
tools:context=".home.HomeFragment">
<ImageButton <ImageButton
android:id="@+id/menuButton" android:id="@+id/menuButton"
android:layout_width="@dimen/glyph_button_height" android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height" android:layout_height="@dimen/glyph_button_height"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_menu" android:src="@drawable/ic_menu"
android:tint="?attr/menuButtonTint" android:tint="?attr/menuButtonTint"
android:contentDescription="@string/content_description_menu" android:contentDescription="@string/content_description_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/privateBrowsingButton"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?attr/privateBrowsingButtonBackground"
android:src="@drawable/ic_private_browsing"
android:contentDescription="@string/content_description_private_browsing_button"
app:layout_constraintEnd_toStartOf="@id/menuButton"
app:layout_constraintTop_toTopOf="@id/menuButton" />
<ImageView
android:id="@+id/wordmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="42dp"
android:src="?attr/fenixLogo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/menuButton" />
<org.mozilla.fenix.home.SearchView
android:id="@+id/toolbar_wrapper"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginTop="64dp"
android:layout_marginStart="16dp"
android:elevation="@dimen/toolbar_elevation"
android:background="?attr/toolbarWrapperBackground"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/privateBrowsingButton"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?attr/privateBrowsingButtonBackground"
android:src="@drawable/ic_private_browsing"
android:contentDescription="@string/content_description_private_browsing_button"
app:layout_constraintEnd_toStartOf="@id/menuButton"
app:layout_constraintTop_toTopOf="@id/menuButton" />
<ImageView
android:id="@+id/wordmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="42dp"
android:src="?attr/fenixLogo"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wordmark"> app:layout_constraintTop_toBottomOf="@id/menuButton" />
<TextView <org.mozilla.fenix.home.SearchView
android:id="@+id/toolbar" android:id="@+id/toolbar_wrapper"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="12sp" android:layout_marginEnd="16dp"
android:paddingEnd="12sp" android:layout_marginTop="64dp"
android:paddingTop="16sp" android:layout_marginStart="16dp"
android:paddingBottom="16sp" android:elevation="@dimen/toolbar_elevation"
android:drawablePadding="12sp" android:background="?attr/toolbarWrapperBackground"
android:clickable="true" app:layout_constraintEnd_toEndOf="parent"
android:focusable="true" app:layout_constraintStart_toStartOf="parent"
android:gravity="center_vertical" app:layout_constraintTop_toBottomOf="@id/wordmark">
android:text="@string/search_hint"
android:textColor="?attr/toolbarTextColor"
android:textSize="14sp" />
</org.mozilla.fenix.home.SearchView>
<View <TextView
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="12sp"
android:paddingEnd="12sp"
android:paddingTop="16sp"
android:paddingBottom="16sp"
android:drawablePadding="12sp"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:text="@string/search_hint"
android:textColor="?attr/toolbarTextColor"
android:textSize="14sp" />
</org.mozilla.fenix.home.SearchView>
<View
android:id="@+id/homeDivider" android:id="@+id/homeDivider"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"
@ -86,4 +90,5 @@
android:layout_marginStart="40dp" android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"/> android:layout_marginEnd="40dp"/>
</androidx.constraintlayout.motion.widget.MotionLayout> </androidx.constraintlayout.motion.widget.MotionLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="8dp" android:layout_margin="8dp"
android:src="@drawable/ic_add_black_24dp" android:src="@drawable/ic_new"
android:baselineAlignBottom="true" android:baselineAlignBottom="true"
app:layout_constraintBaseline_toBaselineOf="@id/header_text" app:layout_constraintBaseline_toBaselineOf="@id/header_text"
app:layout_constraintEnd_toStartOf="@id/tabs_overflow_button"/> app:layout_constraintEnd_toStartOf="@id/tabs_overflow_button"/>

View File

@ -42,7 +42,7 @@
<ImageView android:id="@+id/close_tab_button" <ImageView android:id="@+id/close_tab_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/ic_close_black_24dp" android:src="@drawable/ic_close"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:contentDescription="@string/close_tab" android:contentDescription="@string/close_tab"
app:layout_constraintBottom_toBottomOf="@id/text_url" app:layout_constraintBottom_toBottomOf="@id/text_url"

View File

@ -139,4 +139,10 @@
<p>%1$s puts you in control.</p> <p>%1$s puts you in control.</p>
<p>%1$s is produced by Mozilla. Our mission is to foster a healthy, open Internet.<br/> <p>%1$s is produced by Mozilla. Our mission is to foster a healthy, open Internet.<br/>
]]></string> ]]></string>
<!-- Current session overflow menu -->
<string name="current_session_delete">Delete</string>
<string name="current_session_archive">Archive</string>
<string name="current_session_send_and_share">Send and Share</string>
<string name="current_session_image">Current session image</string>
</resources> </resources>

View File

@ -116,4 +116,13 @@
<item name="android:minHeight">0dp</item> <item name="android:minHeight">0dp</item>
<item name="android:background">@drawable/search_pill_background</item> <item name="android:background">@drawable/search_pill_background</item>
</style> </style>
<style name="CurrentSessionBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/CurrentSessionBottomSheetStyle</item>
</style>
<style name="CurrentSessionBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
<item name="android:textColor">@android:color/black</item>
</style>
</resources> </resources>