1
0
Fork 0

Fixes #557: Selected tab should appear with selected theme

master
Colin Lee 2019-02-16 20:55:49 -06:00 committed by Jeff Boek
parent 8fcef90c4a
commit b42a512b87
4 changed files with 93 additions and 29 deletions

View File

@ -29,6 +29,7 @@ import org.mozilla.fenix.home.tabs.TabsAction
import org.mozilla.fenix.home.tabs.TabsChange import org.mozilla.fenix.home.tabs.TabsChange
import org.mozilla.fenix.home.tabs.TabsComponent import org.mozilla.fenix.home.tabs.TabsComponent
import org.mozilla.fenix.home.tabs.TabsState import org.mozilla.fenix.home.tabs.TabsState
import org.mozilla.fenix.home.tabs.toSessionViewState
import org.mozilla.fenix.isPrivate import org.mozilla.fenix.isPrivate
import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable import org.mozilla.fenix.mvi.getAutoDisposeObservable
@ -46,8 +47,10 @@ class HomeFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false) val view = inflater.inflate(R.layout.fragment_home, container, false)
val sessionManager = requireComponents.core.sessionManager
TabsComponent(view.homeLayout, bus, (activity as HomeActivity).browsingModeManager.isPrivate, TabsComponent(view.homeLayout, bus, (activity as HomeActivity).browsingModeManager.isPrivate,
TabsState(requireComponents.core.sessionManager.sessions)) TabsState(sessionManager.sessions.map { it.toSessionViewState(it == sessionManager.selectedSession) })
)
SessionsComponent(view.homeLayout, bus, (activity as HomeActivity).browsingModeManager.isPrivate) SessionsComponent(view.homeLayout, bus, (activity as HomeActivity).browsingModeManager.isPrivate)
layoutComponents(view) layoutComponents(view)
ActionBusFactory.get(this).logMergedObservables() ActionBusFactory.get(this).logMergedObservables()
@ -66,13 +69,17 @@ class HomeFragment : Fragment() {
.subscribe { .subscribe {
when (it) { when (it) {
is TabsAction.Select -> { is TabsAction.Select -> {
requireComponents.core.sessionManager.select(it.session) val session = requireComponents.core.sessionManager.findSessionById(it.sessionId)
val directions = HomeFragmentDirections.actionHomeFragmentToBrowserFragment(it.session.id, requireComponents.core.sessionManager.select(session!!)
val directions = HomeFragmentDirections.actionHomeFragmentToBrowserFragment(
it.sessionId,
(activity as HomeActivity).browsingModeManager.isPrivate) (activity as HomeActivity).browsingModeManager.isPrivate)
Navigation.findNavController(view).navigate(directions) Navigation.findNavController(view).navigate(directions)
} }
is TabsAction.Close -> { is TabsAction.Close -> {
requireComponents.core.sessionManager.remove(it.session) requireComponents.core.sessionManager.findSessionById(it.sessionId)?.let { session ->
requireComponents.core.sessionManager.remove(session)
}
} }
} }
} }
@ -167,37 +174,62 @@ class HomeFragment : Fragment() {
val observer = object : SessionManager.Observer { val observer = object : SessionManager.Observer {
override fun onSessionAdded(session: Session) { override fun onSessionAdded(session: Session) {
super.onSessionAdded(session) super.onSessionAdded(session)
val sessionManager = requireComponents.core.sessionManager
getManagedEmitter<TabsChange>().onNext( getManagedEmitter<TabsChange>().onNext(
TabsChange.Changed(requireComponents.core.sessionManager.sessions TabsChange.Changed(
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private })) sessionManager.sessions
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { it.toSessionViewState(it == sessionManager.selectedSession) }
)
)
} }
override fun onSessionRemoved(session: Session) { override fun onSessionRemoved(session: Session) {
super.onSessionRemoved(session) super.onSessionRemoved(session)
val sessionManager = requireComponents.core.sessionManager
getManagedEmitter<TabsChange>().onNext( getManagedEmitter<TabsChange>().onNext(
TabsChange.Changed(requireComponents.core.sessionManager.sessions TabsChange.Changed(
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private })) sessionManager.sessions
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { it.toSessionViewState(it == sessionManager.selectedSession) }
)
)
} }
override fun onSessionSelected(session: Session) { override fun onSessionSelected(session: Session) {
super.onSessionSelected(session) super.onSessionSelected(session)
val sessionManager = requireComponents.core.sessionManager
getManagedEmitter<TabsChange>().onNext( getManagedEmitter<TabsChange>().onNext(
TabsChange.Changed(requireComponents.core.sessionManager.sessions TabsChange.Changed(
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private })) sessionManager.sessions
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { it.toSessionViewState(it == sessionManager.selectedSession) }
)
)
} }
override fun onSessionsRestored() { override fun onSessionsRestored() {
super.onSessionsRestored() super.onSessionsRestored()
val sessionManager = requireComponents.core.sessionManager
getManagedEmitter<TabsChange>().onNext( getManagedEmitter<TabsChange>().onNext(
TabsChange.Changed(requireComponents.core.sessionManager.sessions TabsChange.Changed(
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private })) sessionManager.sessions
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { it.toSessionViewState(it == sessionManager.selectedSession) }
)
)
} }
override fun onAllSessionsRemoved() { override fun onAllSessionsRemoved() {
super.onAllSessionsRemoved() super.onAllSessionsRemoved()
val sessionManager = requireComponents.core.sessionManager
getManagedEmitter<TabsChange>().onNext( getManagedEmitter<TabsChange>().onNext(
TabsChange.Changed(requireComponents.core.sessionManager.sessions TabsChange.Changed(
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private })) sessionManager.sessions
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { it.toSessionViewState(it == sessionManager.selectedSession) }
)
)
} }
} }
requireComponents.core.sessionManager.register(observer) requireComponents.core.sessionManager.register(observer)

View File

@ -13,14 +13,13 @@ import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observer import io.reactivex.Observer
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.tab_list_row.* import kotlinx.android.synthetic.main.tab_list_row.*
import mozilla.components.browser.session.Session
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.increaseTapArea
class TabsAdapter(private val actionEmitter: Observer<TabsAction>) : class TabsAdapter(private val actionEmitter: Observer<TabsAction>) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() { RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var sessions = listOf<Session>() var sessions = listOf<SessionViewState>()
set(value) { set(value) {
val diffResult = DiffUtil.calculateDiff(TabsDiffCallback(field, value), true) val diffResult = DiffUtil.calculateDiff(TabsDiffCallback(field, value), true)
field = value field = value
@ -44,31 +43,50 @@ class TabsAdapter(private val actionEmitter: Observer<TabsAction>) :
} }
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isEmpty()) onBindViewHolder(holder, position)
else if (holder is TabViewHolder) {
val bundle = payloads[0] as Bundle
bundle.getString(tab_url)?.apply(holder::updateUrl)
bundle.getBoolean(tab_selected).apply(holder::updateSelected)
}
}
private class TabViewHolder( private class TabViewHolder(
view: View, val view: View,
actionEmitter: Observer<TabsAction>, actionEmitter: Observer<TabsAction>,
override val containerView: View? = view override val containerView: View? = view
) : ) :
RecyclerView.ViewHolder(view), LayoutContainer { RecyclerView.ViewHolder(view), LayoutContainer {
var session: Session? = null var session: SessionViewState? = null
init { init {
item_tab.setOnClickListener { item_tab.setOnClickListener {
actionEmitter.onNext(TabsAction.Select(session!!)) actionEmitter.onNext(TabsAction.Select(session?.id!!))
} }
close_tab_button?.run { close_tab_button?.run {
increaseTapArea(closeButtonIncreaseDps) increaseTapArea(closeButtonIncreaseDps)
setOnClickListener { setOnClickListener {
actionEmitter.onNext(TabsAction.Close(session!!)) actionEmitter.onNext(TabsAction.Close(session?.id!!))
} }
} }
} }
fun bindSession(session: Session) { fun bindSession(session: SessionViewState) {
this.session = session this.session = session
text_url.text = session.url updateUrl(session.url)
updateSelected(session.selected)
}
fun updateUrl(url: String) {
text_url.text = url
}
fun updateSelected(selected: Boolean) {
item_tab.background = if (selected)
view.context.getDrawable(R.drawable.session_border) else null
} }
companion object { companion object {
@ -76,11 +94,16 @@ class TabsAdapter(private val actionEmitter: Observer<TabsAction>) :
const val LAYOUT_ID = R.layout.tab_list_row const val LAYOUT_ID = R.layout.tab_list_row
} }
} }
companion object {
const val tab_url = "url"
const val tab_selected = "selected"
}
} }
class TabsDiffCallback( class TabsDiffCallback(
private val oldList: List<Session>, private val oldList: List<SessionViewState>,
private val newList: List<Session> private val newList: List<SessionViewState>
) : DiffUtil.Callback() { ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size override fun getOldListSize(): Int = oldList.size
@ -99,7 +122,10 @@ class TabsDiffCallback(
val newSession = newList[newItemPosition] val newSession = newList[newItemPosition]
val diffBundle = Bundle() val diffBundle = Bundle()
if (oldSession.url != newSession.url) { if (oldSession.url != newSession.url) {
diffBundle.putString("url", newSession.url) diffBundle.putString(TabsAdapter.tab_url, newSession.url)
}
if (oldSession.selected != newSession.selected) {
diffBundle.putBoolean(TabsAdapter.tab_selected, newSession.selected)
} }
return if (diffBundle.size() == 0) null else diffBundle return if (diffBundle.size() == 0) null else diffBundle
} }

View File

@ -36,13 +36,18 @@ class TabsComponent(
} }
} }
data class TabsState(val sessions: List<Session>) : ViewState data class TabsState(val sessions: List<SessionViewState>) : ViewState
data class SessionViewState(val id: String, val url: String, val selected: Boolean)
fun Session.toSessionViewState(selected: Boolean): SessionViewState {
return SessionViewState(this.id, this.url, selected)
}
sealed class TabsAction : Action { sealed class TabsAction : Action {
data class Select(val session: Session) : TabsAction() data class Select(val sessionId: String) : TabsAction()
data class Close(val session: Session) : TabsAction() data class Close(val sessionId: String) : TabsAction()
} }
sealed class TabsChange : Change { sealed class TabsChange : Change {
data class Changed(val sessions: List<Session>) : TabsChange() data class Changed(val sessions: List<SessionViewState>) : TabsChange()
} }

View File

@ -25,6 +25,7 @@
android:tint="@android:color/black" android:tint="@android:color/black"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:paddingTop="4dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:contentDescription="@string/favicon_content_description"/> android:contentDescription="@string/favicon_content_description"/>