[fenix] For https://github.com/mozilla-mobile/fenix/issues/1817: Multi-select toolbar changes when minimized

pull/600/head
Colin Lee 6 years ago
parent fc61d849a5
commit f3ad87cbd2

@ -53,6 +53,7 @@ class BookmarkComponent(
) )
state.copy(mode = mode) state.copy(mode = mode)
} }
is BookmarkChange.ClearSelection -> state.copy(mode = BookmarkState.Mode.Normal)
} }
} }
@ -64,7 +65,7 @@ class BookmarkComponent(
} }
} }
data class BookmarkState(val tree: BookmarkNode?, val mode: BookmarkState.Mode) : ViewState { data class BookmarkState(val tree: BookmarkNode?, val mode: Mode) : ViewState {
sealed class Mode { sealed class Mode {
object Normal : Mode() object Normal : Mode()
data class Selecting(val selectedItems: Set<BookmarkNode>) : Mode() data class Selecting(val selectedItems: Set<BookmarkNode>) : Mode()
@ -90,6 +91,7 @@ sealed class BookmarkChange : Change {
data class Change(val tree: BookmarkNode) : BookmarkChange() data class Change(val tree: BookmarkNode) : BookmarkChange()
data class IsSelected(val newlySelectedItem: BookmarkNode) : BookmarkChange() data class IsSelected(val newlySelectedItem: BookmarkNode) : BookmarkChange()
data class IsDeselected(val newlyDeselectedItem: BookmarkNode) : BookmarkChange() data class IsDeselected(val newlyDeselectedItem: BookmarkNode) : BookmarkChange()
object ClearSelection : BookmarkChange()
} }
operator fun BookmarkNode.contains(item: BookmarkNode): Boolean { operator fun BookmarkNode.contains(item: BookmarkNode): Boolean {

@ -17,14 +17,11 @@ import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.appcompat.widget.ActionMenuView
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import androidx.navigation.NavController
import androidx.navigation.Navigation import androidx.navigation.Navigation
import kotlinx.android.synthetic.main.fragment_bookmark.view.* import kotlinx.android.synthetic.main.fragment_bookmark.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -46,7 +43,6 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.allowUndo import org.mozilla.fenix.ext.allowUndo
import org.mozilla.fenix.ext.getColorIntFromAttr
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.share import org.mozilla.fenix.ext.share
import org.mozilla.fenix.ext.urlToHost import org.mozilla.fenix.ext.urlToHost
@ -62,6 +58,14 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
private lateinit var bookmarkComponent: BookmarkComponent private lateinit var bookmarkComponent: BookmarkComponent
private lateinit var signInComponent: SignInComponent private lateinit var signInComponent: SignInComponent
private var currentRoot: BookmarkNode? = null private var currentRoot: BookmarkNode? = null
private val navigation by lazy { Navigation.findNavController(requireActivity(), R.id.container) }
private val onDestinationChangedListener =
NavController.OnDestinationChangedListener { _, destination, args ->
if (destination.id != R.id.bookmarkFragment ||
args != null && BookmarkFragmentArgs.fromBundle(args).currentRoot != currentRoot?.guid
)
getManagedEmitter<BookmarkChange>().onNext(BookmarkChange.ClearSelection)
}
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
get() = Main + job get() = Main + job
@ -85,13 +89,13 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
(activity as AppCompatActivity).supportActionBar?.show() (activity as AppCompatActivity).supportActionBar?.show()
checkIfSignedIn() checkIfSignedIn()
navigation.addOnDestinationChangedListener(onDestinationChangedListener)
val currentGuid = BookmarkFragmentArgs.fromBundle(arguments!!).currentRoot.ifEmpty { BookmarkRoot.Root.id } val currentGuid = BookmarkFragmentArgs.fromBundle(arguments!!).currentRoot.ifEmpty { BookmarkRoot.Root.id }
launch(IO) { launch(IO) {
currentRoot = requireComponents.core.bookmarksStorage.getTree(currentGuid) as BookmarkNode currentRoot = requireComponents.core.bookmarksStorage.getTree(currentGuid) as BookmarkNode
launch(Main) { launch(Main) {
if (currentGuid != BookmarkRoot.Root.id) (activity as HomeActivity).title = currentRoot!!.title
getManagedEmitter<BookmarkChange>().onNext(BookmarkChange.Change(currentRoot!!)) getManagedEmitter<BookmarkChange>().onNext(BookmarkChange.Change(currentRoot!!))
activity?.run { activity?.run {
@ -108,114 +112,26 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
?: getManagedEmitter<SignInChange>().onNext(SignInChange.SignedOut) ?: getManagedEmitter<SignInChange>().onNext(SignInChange.SignedOut)
} }
fun setToolbarColors(foreground: Int, background: Int) {
val toolbar = (activity as AppCompatActivity).findViewById<Toolbar>(R.id.navigationToolbar)
val colorFilter = PorterDuffColorFilter(
ContextCompat.getColor(context!!, foreground), PorterDuff.Mode.SRC_IN
)
toolbar.setBackgroundColor(ContextCompat.getColor(context!!, background))
toolbar.setTitleTextColor(ContextCompat.getColor(context!!, foreground))
themeToolbar(
toolbar, foreground,
background, colorFilter
)
}
override fun onStop() {
super.onStop()
// Reset the toolbar color
setToolbarColors(
R.attr.primaryText.getColorIntFromAttr(context!!),
R.attr.foundation.getColorIntFromAttr(context!!)
)
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
navigation.removeOnDestinationChangedListener(onDestinationChangedListener)
job.cancel() job.cancel()
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
val toolbar = (activity as AppCompatActivity).findViewById<Toolbar>(R.id.navigationToolbar)
when (val mode = (bookmarkComponent.uiView as BookmarkUIView).mode) { when (val mode = (bookmarkComponent.uiView as BookmarkUIView).mode) {
BookmarkState.Mode.Normal -> { BookmarkState.Mode.Normal -> {
inflater.inflate(R.menu.library_menu, menu) inflater.inflate(R.menu.library_menu, menu)
activity?.title =
if (currentRoot?.title in setOf(
"root",
null
)
) getString(R.string.library_bookmarks) else currentRoot!!.title
setToolbarColors(
R.attr.primaryText.getColorIntFromAttr(context!!),
R.attr.foundation.getColorIntFromAttr(context!!)
)
} }
is BookmarkState.Mode.Selecting -> { is BookmarkState.Mode.Selecting -> {
inflater.inflate(R.menu.bookmarks_select_multi, menu) inflater.inflate(R.menu.bookmarks_select_multi, menu)
menu.findItem(R.id.edit_bookmark_multi_select)?.run {
menu.findItem(R.id.edit_bookmark_multi_select).run {
isVisible = mode.selectedItems.size == 1 isVisible = mode.selectedItems.size == 1
icon.colorFilter = PorterDuffColorFilter( icon.colorFilter = PorterDuffColorFilter(
ContextCompat.getColor(context!!, R.color.white_color), ContextCompat.getColor(context!!, R.color.white_color),
PorterDuff.Mode.SRC_IN PorterDuff.Mode.SRC_IN
) )
} }
activity?.title = getString(R.string.bookmarks_multi_select_title, mode.selectedItems.size)
setToolbarColors(
R.color.white_color,
R.attr.accentBright.getColorIntFromAttr(context!!)
)
}
}
}
private fun themeToolbar(
toolbar: Toolbar,
textColor: Int,
backgroundColor: Int,
colorFilter: PorterDuffColorFilter? = null
) {
toolbar.setTitleTextColor(ContextCompat.getColor(context!!, textColor))
toolbar.setBackgroundColor(ContextCompat.getColor(context!!, backgroundColor))
if (colorFilter == null) {
return
}
toolbar.overflowIcon?.colorFilter = colorFilter
(0 until toolbar.childCount).forEach {
when (val item = toolbar.getChildAt(it)) {
is ImageButton -> item.drawable.colorFilter = colorFilter
is ActionMenuView -> themeActionMenuView(item, colorFilter)
}
}
}
private fun themeActionMenuView(
item: ActionMenuView,
colorFilter: PorterDuffColorFilter
) {
(0 until item.childCount).forEach {
val innerChild = item.getChildAt(it)
if (innerChild is ActionMenuItemView) {
themeChildren(innerChild, item, colorFilter)
}
}
}
private fun themeChildren(
innerChild: ActionMenuItemView,
item: ActionMenuView,
colorFilter: PorterDuffColorFilter
) {
val drawables = innerChild.compoundDrawables
for (k in drawables.indices) {
drawables[k]?.let {
item.post { innerChild.compoundDrawables[k].colorFilter = colorFilter }
} }
} }
} }
@ -236,14 +152,14 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
requireComponents.analytics.metrics.track(Event.OpenedBookmark) requireComponents.analytics.metrics.track(Event.OpenedBookmark)
} }
is BookmarkAction.Expand -> { is BookmarkAction.Expand -> {
Navigation.findNavController(requireActivity(), R.id.container) navigation
.navigate(BookmarkFragmentDirections.actionBookmarkFragmentSelf(it.folder.guid)) .navigate(BookmarkFragmentDirections.actionBookmarkFragmentSelf(it.folder.guid))
} }
is BookmarkAction.BackPressed -> { is BookmarkAction.BackPressed -> {
Navigation.findNavController(requireActivity(), R.id.container).popBackStack() navigation.popBackStack()
} }
is BookmarkAction.Edit -> { is BookmarkAction.Edit -> {
Navigation.findNavController(requireActivity(), R.id.container) navigation
.navigate( .navigate(
BookmarkFragmentDirections BookmarkFragmentDirections
.actionBookmarkFragmentToBookmarkEditFragment(it.item.guid) .actionBookmarkFragmentToBookmarkEditFragment(it.item.guid)
@ -310,7 +226,7 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { return when (item.itemId) {
R.id.libraryClose -> { R.id.libraryClose -> {
Navigation.findNavController(requireActivity(), R.id.container) navigation
.popBackStack(R.id.libraryFragment, true) .popBackStack(R.id.libraryFragment, true)
true true
} }
@ -322,14 +238,14 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
} }
(activity as HomeActivity).browsingModeManager.mode = BrowsingModeManager.Mode.Normal (activity as HomeActivity).browsingModeManager.mode = BrowsingModeManager.Mode.Normal
Navigation.findNavController(requireActivity(), R.id.container) navigation
.navigate(BookmarkFragmentDirections.actionBookmarkFragmentToHomeFragment()) .navigate(BookmarkFragmentDirections.actionBookmarkFragmentToHomeFragment())
requireComponents.analytics.metrics.track(Event.OpenedBookmarksInNewTabs) requireComponents.analytics.metrics.track(Event.OpenedBookmarksInNewTabs)
true true
} }
R.id.edit_bookmark_multi_select -> { R.id.edit_bookmark_multi_select -> {
val bookmark = getSelectedBookmarks().first() val bookmark = getSelectedBookmarks().first()
Navigation.findNavController(requireActivity(), R.id.container) navigation
.navigate( .navigate(
BookmarkFragmentDirections BookmarkFragmentDirections
.actionBookmarkFragmentToBookmarkEditFragment(bookmark.guid) .actionBookmarkFragmentToBookmarkEditFragment(bookmark.guid)
@ -344,7 +260,7 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
} }
(activity as HomeActivity).browsingModeManager.mode = BrowsingModeManager.Mode.Private (activity as HomeActivity).browsingModeManager.mode = BrowsingModeManager.Mode.Private
Navigation.findNavController(requireActivity(), R.id.container) navigation
.navigate(BookmarkFragmentDirections.actionBookmarkFragmentToHomeFragment()) .navigate(BookmarkFragmentDirections.actionBookmarkFragmentToHomeFragment())
requireComponents.analytics.metrics.track(Event.OpenedBookmarksInPrivateTabs) requireComponents.analytics.metrics.track(Event.OpenedBookmarksInPrivateTabs)
true true

@ -4,9 +4,17 @@
package org.mozilla.fenix.library.bookmarks package org.mozilla.fenix.library.bookmarks
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.appcompat.widget.ActionMenuView
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
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
@ -15,6 +23,8 @@ import mozilla.appservices.places.BookmarkRoot
import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.support.base.feature.BackHandler import mozilla.components.support.base.feature.BackHandler
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.ext.getColorIntFromAttr
import org.mozilla.fenix.mvi.UIView import org.mozilla.fenix.mvi.UIView
class BookmarkUIView( class BookmarkUIView(
@ -28,12 +38,14 @@ class BookmarkUIView(
var mode: BookmarkState.Mode = BookmarkState.Mode.Normal var mode: BookmarkState.Mode = BookmarkState.Mode.Normal
private set private set
var canGoBack = false private var canGoBack = false
override val view: LinearLayout = LayoutInflater.from(container.context) override val view: LinearLayout = LayoutInflater.from(container.context)
.inflate(R.layout.component_bookmark, container, true) as LinearLayout .inflate(R.layout.component_bookmark, container, true) as LinearLayout
private val bookmarkAdapter: BookmarkAdapter private val bookmarkAdapter: BookmarkAdapter
private val context = container.context
private val activity = context?.asActivity()
init { init {
view.bookmark_list.apply { view.bookmark_list.apply {
@ -48,6 +60,10 @@ class BookmarkUIView(
if (it.mode != mode) { if (it.mode != mode) {
mode = it.mode mode = it.mode
actionEmitter.onNext(BookmarkAction.ModeChanged) actionEmitter.onNext(BookmarkAction.ModeChanged)
when (val modeCopy = mode) {
is BookmarkState.Mode.Normal -> setUIForNormalMode(it.tree)
is BookmarkState.Mode.Selecting -> setUIForSelectingMode(modeCopy)
}
} }
} }
@ -59,4 +75,89 @@ class BookmarkUIView(
} }
fun getSelected(): Set<BookmarkNode> = bookmarkAdapter.selected fun getSelected(): Set<BookmarkNode> = bookmarkAdapter.selected
private fun setToolbarColors(foreground: Int, background: Int) {
val toolbar = (activity as AppCompatActivity).findViewById<Toolbar>(R.id.navigationToolbar)
val colorFilter = PorterDuffColorFilter(
ContextCompat.getColor(context, foreground), PorterDuff.Mode.SRC_IN
)
toolbar.setBackgroundColor(ContextCompat.getColor(context, background))
toolbar.setTitleTextColor(ContextCompat.getColor(context, foreground))
themeToolbar(
toolbar, foreground,
background, colorFilter
)
}
private fun setUIForSelectingMode(
mode: BookmarkState.Mode.Selecting
) {
activity?.title = context.getString(R.string.bookmarks_multi_select_title, mode.selectedItems.size)
setToolbarColors(
R.color.white_color,
R.attr.accentBright.getColorIntFromAttr(context!!)
)
}
private fun setUIForNormalMode(root: BookmarkNode?) {
activity?.title =
if (root?.title in setOf(
"root",
null
)
) context.getString(R.string.library_bookmarks) else root!!.title
setToolbarColors(
R.attr.primaryText.getColorIntFromAttr(context!!),
R.attr.foundation.getColorIntFromAttr(context)
)
}
private fun themeToolbar(
toolbar: Toolbar,
textColor: Int,
backgroundColor: Int,
colorFilter: PorterDuffColorFilter? = null
) {
toolbar.setTitleTextColor(ContextCompat.getColor(context!!, textColor))
toolbar.setBackgroundColor(ContextCompat.getColor(context, backgroundColor))
if (colorFilter == null) {
return
}
toolbar.overflowIcon?.colorFilter = colorFilter
(0 until toolbar.childCount).forEach {
when (val item = toolbar.getChildAt(it)) {
is ImageButton -> item.drawable.colorFilter = colorFilter
is ActionMenuView -> themeActionMenuView(item, colorFilter)
}
}
}
private fun themeActionMenuView(
item: ActionMenuView,
colorFilter: PorterDuffColorFilter
) {
(0 until item.childCount).forEach {
val innerChild = item.getChildAt(it)
if (innerChild is ActionMenuItemView) {
themeChildren(innerChild, item, colorFilter)
}
}
}
private fun themeChildren(
innerChild: ActionMenuItemView,
item: ActionMenuView,
colorFilter: PorterDuffColorFilter
) {
val drawables = innerChild.compoundDrawables
for (k in drawables.indices) {
drawables[k]?.let {
item.post { innerChild.compoundDrawables[k].colorFilter = colorFilter }
}
}
}
} }

Loading…
Cancel
Save