Commit 11940fba authored by MozLando's avatar MozLando
Browse files

Merge #6908

6908: 🎲

 For #6907 - Dispatches tabsTray update when MediaState changes. r=jonalmeida,csadilek a=boek
Co-authored-by: default avatarJeff Boek <jeff@jeffboek.com>
parents b8a37bae 3dc55a7f
......@@ -28,6 +28,7 @@ android {
dependencies {
api project(':concept-tabstray')
implementation project(':ui-icons')
implementation project(':ui-colors')
implementation project(':support-base')
......
......@@ -22,8 +22,9 @@ android {
}
dependencies {
implementation project(':support-base')
api project(':concept-engine')
implementation project(':support-base')
implementation Dependencies.kotlin_stdlib
}
......
......@@ -5,6 +5,7 @@
package mozilla.components.concept.tabstray
import android.graphics.Bitmap
import mozilla.components.concept.engine.media.Media
/**
* Data class representing a tab to be displayed in a [TabsTray].
......@@ -14,11 +15,13 @@ import android.graphics.Bitmap
* @property title Current title of the tab (or an empty [String]]).
* @property icon Current icon of the tab (or null)
* @property thumbnail Current thumbnail of the tab (or null)
* @property mediaState Current media state for the tab (or null)
*/
data class Tab(
val id: String,
val url: String,
val title: String = "",
val icon: Bitmap? = null,
val thumbnail: Bitmap? = null
val thumbnail: Bitmap? = null,
val mediaState: Media.State? = null
)
......@@ -5,14 +5,22 @@
package mozilla.components.feature.tabs.ext
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.MediaState
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.concept.tabstray.Tabs
private fun BrowserState.mediaStateForTab(tab: TabSessionState): MediaState.State =
if (media.aggregate.activeTabId == tab.id) {
media.aggregate.state
} else {
MediaState.State.NONE
}
internal fun BrowserState.toTabs(
tabsFilter: (TabSessionState) -> Boolean = { true }
) = Tabs(
list = tabs
.filter(tabsFilter)
.map { it.toTab() },
.map { it.toTab(mediaStateForTab(it)) },
selectedIndex = tabs.indexOfFirst { it.id == selectedTabId }
)
......@@ -4,13 +4,20 @@
package mozilla.components.feature.tabs.ext
import mozilla.components.browser.state.state.MediaState
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.concept.engine.media.Media
import mozilla.components.concept.tabstray.Tab
internal fun TabSessionState.toTab() = Tab(
internal fun TabSessionState.toTab(mediaState: MediaState.State) = Tab(
id,
content.url,
content.title,
content.icon,
content.thumbnail
content.thumbnail,
when (mediaState) {
MediaState.State.PLAYING -> Media.State.PLAYING
MediaState.State.PAUSED -> Media.State.PAUSED
else -> null
}
)
......@@ -42,10 +42,9 @@ class TabsTrayPresenter(
}
private suspend fun collect(flow: Flow<BrowserState>) {
flow.map { state -> state.toTabs(tabsFilter) }
flow.map { it.toTabs(tabsFilter) }
.ifChanged()
.collect { tabs ->
// Do not invoke the callback on start if this is the initial state.
if (tabs.list.isEmpty() && this.tabs != null) {
closeTabsTray.invoke()
......
/* 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 mozilla.components.feature.tabs.ext
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.MediaState
import mozilla.components.browser.state.state.createTab
import mozilla.components.concept.engine.media.Media
import org.junit.Test
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
class TabSessionStateTest {
@Test
fun `mediaState gets set correctly`() {
var browserState = BrowserState(
tabs = listOf(
createTab("https://www.mozilla.org", id = "a"),
createTab("https://getpocket.com", id = "b"),
createTab("https://developer.mozilla.org", id = "c"),
createTab("https://www.firefox.com", id = "d"),
createTab("https://www.google.com", id = "e")
),
selectedTabId = "a",
media = MediaState(MediaState.Aggregate(activeTabId = "a", state = MediaState.State.PLAYING))
)
var tabs = browserState.toTabs()
assertEquals(Media.State.PLAYING, tabs.list[0].mediaState)
browserState = browserState.copy(
media = MediaState(MediaState.Aggregate(activeTabId = "b", state = MediaState.State.PAUSED))
)
tabs = browserState.toTabs()
assertNull(tabs.list[0].mediaState)
assertEquals(Media.State.PAUSED, tabs.list[1].mediaState)
}
}
......@@ -12,13 +12,16 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import mozilla.components.browser.state.action.MediaAction
import mozilla.components.browser.state.action.TabListAction
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.MediaState
import mozilla.components.browser.state.state.createTab
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.tabstray.Tabs
import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.feature.tabs.ext.toTabs
import mozilla.components.support.test.any
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.mock
import org.junit.After
......@@ -216,6 +219,38 @@ class TabsTrayPresenterTest {
verify(tabsTray).onTabsChanged(3, 1)
}
@Test
fun `tabs tray will get updated if mediaState changes`() {
val store = BrowserStore(
BrowserState(
tabs = listOf(
createTab("https://www.mozilla.org", id = "a"),
createTab("https://getpocket.com", id = "b"),
createTab("https://developer.mozilla.org", id = "c"),
createTab("https://www.firefox.com", id = "d"),
createTab("https://www.google.com", id = "e")
),
selectedTabId = "a"
)
)
val tabsTray: MockedTabsTray = spy(MockedTabsTray())
val presenter = TabsTrayPresenter(tabsTray, store, { true }, mock())
presenter.start()
testDispatcher.advanceUntilIdle()
store.dispatch(
MediaAction.UpdateMediaAggregateAction(
store.state.media.aggregate.copy(activeTabId = "a", state = MediaState.State.PLAYING)
)
).joinBlocking()
testDispatcher.advanceUntilIdle()
verify(tabsTray, times(2)).updateTabs(any())
}
@Test
fun `presenter will close tabs tray when all sessions get removed`() {
val store = BrowserStore(
......
......@@ -12,6 +12,12 @@ permalink: /changelog/
* [Gecko](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Gecko.kt)
* [Configuration](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Config.kt)
* **feature-tabs**
* Fixed issue [#6907](https://github.com/mozilla-mobile/android-components/issues/6907). Uses MediaState when mapping BrowserState to tabs.
* **concept-tabstray**
* For issue [#6907](https://github.com/mozilla-mobile/android-components/issues/6907). Adds `Media.State` to `Tab`
* **feature-session**
* ⚠️ **This is a breaking change**: Added optional `crashReporting` param to [PictureInPictureFeature] so we can record caught exceptions.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment