Update to new feature-media API.
parent
cd7c2c4bd5
commit
02aabea14a
|
@ -213,6 +213,9 @@
|
|||
android:exported="false"
|
||||
android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar"/>
|
||||
|
||||
<service android:name=".media.MediaService"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".customtabs.CustomTabsService"
|
||||
android:exported="true"
|
||||
|
|
|
@ -10,20 +10,6 @@ object FeatureFlags {
|
|||
*/
|
||||
const val pullToRefreshEnabled = false
|
||||
|
||||
/**
|
||||
* Integration of media features provided by `feature-media` component:
|
||||
* - Background playback without the app getting killed
|
||||
* - Media notification with play/pause controls
|
||||
* - Audio Focus handling (pausing/resuming in agreement with other media apps)
|
||||
* - Support for hardware controls to toggle play/pause (e.g. buttons on a headset)
|
||||
*
|
||||
* Behind nightly flag until all related Android Components issues are fixed and QA has signed
|
||||
* off.
|
||||
*
|
||||
* https://github.com/mozilla-mobile/fenix/issues/4431
|
||||
*/
|
||||
const val mediaIntegration = true
|
||||
|
||||
/**
|
||||
* Allows Progressive Web Apps to be installed to the device home screen.
|
||||
*/
|
||||
|
|
|
@ -16,6 +16,7 @@ import androidx.navigation.fragment.navArgs
|
|||
import kotlinx.android.synthetic.main.fragment_create_collection.view.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import org.mozilla.fenix.R
|
||||
|
@ -45,10 +46,11 @@ class CollectionCreationFragment : DialogFragment() {
|
|||
val args: CollectionCreationFragmentArgs by navArgs()
|
||||
|
||||
val sessionManager = requireComponents.core.sessionManager
|
||||
val store = requireComponents.core.store
|
||||
val publicSuffixList = requireComponents.publicSuffixList
|
||||
val tabs = sessionManager.getTabs(args.tabIds, publicSuffixList)
|
||||
val tabs = sessionManager.getTabs(args.tabIds, store, publicSuffixList)
|
||||
val selectedTabs = if (args.selectedTabIds != null) {
|
||||
sessionManager.getTabs(args.selectedTabIds, publicSuffixList).toSet()
|
||||
sessionManager.getTabs(args.selectedTabIds, store, publicSuffixList).toSet()
|
||||
} else {
|
||||
if (tabs.size == 1) setOf(tabs.first()) else emptySet()
|
||||
}
|
||||
|
@ -80,7 +82,10 @@ class CollectionCreationFragment : DialogFragment() {
|
|||
viewLifecycleOwner.lifecycleScope
|
||||
)
|
||||
)
|
||||
collectionCreationView = CollectionCreationView(view.createCollectionWrapper, collectionCreationInteractor)
|
||||
collectionCreationView = CollectionCreationView(
|
||||
view.createCollectionWrapper,
|
||||
collectionCreationInteractor
|
||||
)
|
||||
|
||||
return view
|
||||
}
|
||||
|
@ -108,9 +113,13 @@ class CollectionCreationFragment : DialogFragment() {
|
|||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
fun SessionManager.getTabs(tabIds: Array<String>?, publicSuffixList: PublicSuffixList): List<Tab> {
|
||||
fun SessionManager.getTabs(
|
||||
tabIds: Array<String>?,
|
||||
store: BrowserStore,
|
||||
publicSuffixList: PublicSuffixList
|
||||
): List<Tab> {
|
||||
return tabIds
|
||||
?.mapNotNull { this.findSessionById(it) }
|
||||
?.map { it.toTab(publicSuffixList) }
|
||||
?.map { it.toTab(store, publicSuffixList) }
|
||||
?: emptyList()
|
||||
}
|
||||
|
|
|
@ -20,8 +20,20 @@ import androidx.transition.AutoTransition
|
|||
import androidx.transition.Transition
|
||||
import androidx.transition.TransitionManager
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.*
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.*
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.back_button
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.collection_constraint_layout
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.name_collection_edittext
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.save_button
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.select_all_button
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.bottom_bar_icon_button
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.bottom_bar_text
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.bottom_button_bar_layout
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.collection_constraint_layout
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.collections_list
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.name_collection_edittext
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.select_all_button
|
||||
import kotlinx.android.synthetic.main.component_collection_creation.view.tab_list
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||
import mozilla.components.support.ktx.android.view.showKeyboard
|
||||
|
@ -253,7 +265,8 @@ class CollectionCreationView(
|
|||
tab.id.toString(),
|
||||
tab.url,
|
||||
tab.url.toShortUrl(view.context.components.publicSuffixList),
|
||||
tab.title
|
||||
tab.title,
|
||||
mediaState = MediaState.State.NONE
|
||||
)
|
||||
}.let { tabs ->
|
||||
collectionCreationTabListAdapter.updateData(tabs, tabs.toSet(), true)
|
||||
|
|
|
@ -27,9 +27,8 @@ import mozilla.components.concept.engine.Engine
|
|||
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
|
||||
import mozilla.components.concept.fetch.Client
|
||||
import mozilla.components.feature.customtabs.store.CustomTabsServiceStore
|
||||
import mozilla.components.feature.media.MediaFeature
|
||||
import mozilla.components.feature.media.RecordingDevicesNotificationFeature
|
||||
import mozilla.components.feature.media.state.MediaStateMachine
|
||||
import mozilla.components.feature.media.middleware.MediaMiddleware
|
||||
import mozilla.components.feature.pwa.ManifestStorage
|
||||
import mozilla.components.feature.pwa.WebAppShortcutManager
|
||||
import mozilla.components.feature.session.HistoryDelegate
|
||||
|
@ -44,6 +43,7 @@ import org.mozilla.fenix.FeatureFlags
|
|||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.media.MediaService
|
||||
import org.mozilla.fenix.test.Mockable
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
@ -66,7 +66,7 @@ class Core(private val context: Context) {
|
|||
preferredColorScheme = getPreferredColorScheme(),
|
||||
automaticFontSizeAdjustment = context.settings().shouldUseAutoSize,
|
||||
fontInflationEnabled = context.settings().shouldUseAutoSize,
|
||||
suspendMediaWhenInactive = !FeatureFlags.mediaIntegration,
|
||||
suspendMediaWhenInactive = false,
|
||||
forceUserScalableContent = context.settings().forceEnableZoom
|
||||
)
|
||||
|
||||
|
@ -97,7 +97,11 @@ class Core(private val context: Context) {
|
|||
* The [BrowserStore] holds the global [BrowserState].
|
||||
*/
|
||||
val store by lazy {
|
||||
BrowserStore()
|
||||
BrowserStore(
|
||||
middleware = listOf(
|
||||
MediaMiddleware(context, MediaService::class.java)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,14 +154,6 @@ class Core(private val context: Context) {
|
|||
.whenSessionsChange()
|
||||
}
|
||||
|
||||
if (FeatureFlags.mediaIntegration) {
|
||||
MediaStateMachine.start(sessionManager)
|
||||
|
||||
// Enable media features like showing an ongoing notification with media controls when
|
||||
// media in web content is playing.
|
||||
MediaFeature(context).enable()
|
||||
}
|
||||
|
||||
WebNotificationFeature(
|
||||
context, engine, icons, R.drawable.ic_status_logo,
|
||||
HomeActivity::class.java
|
||||
|
|
|
@ -6,21 +6,36 @@ package org.mozilla.fenix.ext
|
|||
|
||||
import android.content.Context
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.feature.media.state.MediaState
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import org.mozilla.fenix.home.Tab
|
||||
|
||||
fun Session.toTab(context: Context, selected: Boolean? = null, mediaState: MediaState? = null): Tab =
|
||||
this.toTab(context.components.publicSuffixList, selected, mediaState)
|
||||
fun Session.toTab(context: Context, selected: Boolean? = null): Tab =
|
||||
this.toTab(
|
||||
context.components.core.store,
|
||||
context.components.publicSuffixList,
|
||||
selected
|
||||
)
|
||||
|
||||
fun Session.toTab(publicSuffixList: PublicSuffixList, selected: Boolean? = null, mediaState: MediaState? = null): Tab {
|
||||
fun Session.toTab(store: BrowserStore, publicSuffixList: PublicSuffixList, selected: Boolean? = null): Tab {
|
||||
return Tab(
|
||||
sessionId = this.id,
|
||||
url = this.url,
|
||||
hostname = this.url.toShortUrl(publicSuffixList),
|
||||
title = this.title,
|
||||
selected = selected,
|
||||
mediaState = mediaState,
|
||||
icon = this.icon
|
||||
icon = this.icon,
|
||||
mediaState = getMediaStateForSession(store, this)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getMediaStateForSession(store: BrowserStore, session: Session): MediaState.State {
|
||||
// For now we are looking up the media state for this session in the BrowserStore. Eventually
|
||||
// we will migrate away from Session(Manager) and can use BrowserStore and BrowserState directly.
|
||||
return if (store.state.media.aggregate.activeTabId == session.id) {
|
||||
store.state.media.aggregate.state
|
||||
} else {
|
||||
MediaState.State.NONE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,25 +56,27 @@ import kotlinx.android.synthetic.main.fragment_home.view.sessionControlRecyclerV
|
|||
import kotlinx.android.synthetic.main.fragment_home.view.toolbar
|
||||
import kotlinx.android.synthetic.main.fragment_home.view.toolbarLayout
|
||||
import kotlinx.android.synthetic.main.fragment_home.view.toolbar_wrapper
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import mozilla.appservices.places.BookmarkRoot
|
||||
import mozilla.components.browser.menu.ext.getHighlight
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.concept.sync.AuthType
|
||||
import mozilla.components.concept.sync.OAuthAccount
|
||||
import mozilla.components.feature.media.ext.getSession
|
||||
import mozilla.components.feature.media.state.MediaState
|
||||
import mozilla.components.feature.media.state.MediaStateMachine
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.lib.state.ext.flowScoped
|
||||
import mozilla.components.support.ktx.android.util.dpToPx
|
||||
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
|
@ -108,7 +110,6 @@ import org.mozilla.fenix.whatsnew.WhatsNew
|
|||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@SuppressWarnings("TooManyFunctions", "LargeClass")
|
||||
class HomeFragment : Fragment() {
|
||||
private val homeViewModel: HomeScreenViewModel by viewModels {
|
||||
|
@ -165,7 +166,11 @@ class HomeFragment : Fragment() {
|
|||
super.onCreate(savedInstanceState)
|
||||
postponeEnterTransition()
|
||||
|
||||
val sessionObserver = BrowserSessionsObserver(sessionManager, singleSessionObserver) {
|
||||
val sessionObserver = BrowserSessionsObserver(
|
||||
sessionManager,
|
||||
requireComponents.core.store,
|
||||
singleSessionObserver
|
||||
) {
|
||||
emitSessionChanges()
|
||||
}
|
||||
|
||||
|
@ -205,8 +210,9 @@ class HomeFragment : Fragment() {
|
|||
|
||||
sessionControlInteractor = SessionControlInteractor(
|
||||
DefaultSessionControlController(
|
||||
store = requireComponents.core.store,
|
||||
activity = activity,
|
||||
store = homeFragmentStore,
|
||||
fragmentStore = homeFragmentStore,
|
||||
navController = findNavController(),
|
||||
browsingModeManager = browsingModeManager,
|
||||
lifecycleScope = viewLifecycleOwner.lifecycleScope,
|
||||
|
@ -277,7 +283,6 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@SuppressWarnings("LongMethod")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
@ -895,16 +900,9 @@ class HomeFragment : Fragment() {
|
|||
|
||||
private fun List<Session>.toTabs(): List<Tab> {
|
||||
val selected = sessionManager.selectedSession
|
||||
val mediaStateSession = MediaStateMachine.state.getSession()
|
||||
|
||||
return this.map {
|
||||
val mediaState = if (mediaStateSession?.id == it.id) {
|
||||
MediaStateMachine.state
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
it.toTab(requireContext(), it == selected, mediaState)
|
||||
return map {
|
||||
it.toTab(requireContext(), it == selected)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -973,18 +971,24 @@ class HomeFragment : Fragment() {
|
|||
*/
|
||||
private class BrowserSessionsObserver(
|
||||
private val manager: SessionManager,
|
||||
private val store: BrowserStore,
|
||||
private val observer: Session.Observer,
|
||||
private val onChanged: () -> Unit
|
||||
) : LifecycleObserver {
|
||||
private var scope: CoroutineScope? = null
|
||||
|
||||
/**
|
||||
* Start observing
|
||||
*/
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_START)
|
||||
fun onStart() {
|
||||
MediaStateMachine.register(managerObserver)
|
||||
manager.register(managerObserver)
|
||||
subscribeToAll()
|
||||
|
||||
scope = store.flowScoped { flow ->
|
||||
flow.ifChanged { it.media.aggregate }
|
||||
.collect { onChanged() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -992,7 +996,7 @@ private class BrowserSessionsObserver(
|
|||
*/
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||
fun onStop() {
|
||||
MediaStateMachine.unregister(managerObserver)
|
||||
scope?.cancel()
|
||||
manager.unregister(managerObserver)
|
||||
unsubscribeFromAll()
|
||||
}
|
||||
|
@ -1013,11 +1017,7 @@ private class BrowserSessionsObserver(
|
|||
session.unregister(observer)
|
||||
}
|
||||
|
||||
private val managerObserver = object : SessionManager.Observer, MediaStateMachine.Observer {
|
||||
override fun onStateChanged(state: MediaState) {
|
||||
onChanged()
|
||||
}
|
||||
|
||||
private val managerObserver = object : SessionManager.Observer {
|
||||
override fun onSessionAdded(session: Session) {
|
||||
subscribeTo(session)
|
||||
onChanged()
|
||||
|
|
|
@ -7,7 +7,7 @@ package org.mozilla.fenix.home
|
|||
import android.graphics.Bitmap
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.feature.media.state.MediaState
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.lib.state.Action
|
||||
|
@ -29,8 +29,8 @@ data class Tab(
|
|||
val hostname: String,
|
||||
val title: String,
|
||||
val selected: Boolean? = null,
|
||||
var mediaState: MediaState? = null,
|
||||
val icon: Bitmap? = null
|
||||
val icon: Bitmap? = null,
|
||||
val mediaState: MediaState.State
|
||||
)
|
||||
|
||||
data class TopSiteItem(
|
||||
|
|
|
@ -15,7 +15,6 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.synthetic.main.tab_list_row.*
|
||||
import mozilla.components.feature.media.state.MediaState
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import org.mozilla.fenix.home.OnboardingState
|
||||
|
@ -256,7 +255,7 @@ class SessionControlAdapter(
|
|||
}
|
||||
if (it.shouldUpdateSelected) { holder.updateSelected(it.tab.selected ?: false) }
|
||||
if (it.shouldUpdateMediaState) {
|
||||
holder.updatePlayPauseButton(it.tab.mediaState ?: MediaState.None)
|
||||
holder.updatePlayPauseButton(it.tab.mediaState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.prompt.ShareData
|
||||
import mozilla.components.feature.media.ext.pauseIfPlaying
|
||||
import mozilla.components.feature.media.ext.playIfPaused
|
||||
import mozilla.components.feature.media.state.MediaStateMachine
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.tab.collections.ext.restore
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
|
@ -157,8 +157,9 @@ interface SessionControlController {
|
|||
|
||||
@SuppressWarnings("TooManyFunctions", "LargeClass")
|
||||
class DefaultSessionControlController(
|
||||
private val store: BrowserStore,
|
||||
private val activity: HomeActivity,
|
||||
private val store: HomeFragmentStore,
|
||||
private val fragmentStore: HomeFragmentStore,
|
||||
private val navController: NavController,
|
||||
private val browsingModeManager: BrowsingModeManager,
|
||||
private val lifecycleScope: CoroutineScope,
|
||||
|
@ -266,11 +267,11 @@ class DefaultSessionControlController(
|
|||
}
|
||||
|
||||
override fun handlePauseMediaClicked() {
|
||||
MediaStateMachine.state.pauseIfPlaying()
|
||||
store.state.media.pauseIfPlaying()
|
||||
}
|
||||
|
||||
override fun handlePlayMediaClicked() {
|
||||
MediaStateMachine.state.playIfPaused()
|
||||
store.state.media.playIfPaused()
|
||||
}
|
||||
|
||||
override fun handlePrivateBrowsingLearnMoreClicked() {
|
||||
|
@ -358,7 +359,7 @@ class DefaultSessionControlController(
|
|||
}
|
||||
|
||||
override fun handleToggleCollectionExpanded(collection: TabCollection, expand: Boolean) {
|
||||
store.dispatch(HomeFragmentAction.CollectionExpanded(collection, expand))
|
||||
fragmentStore.dispatch(HomeFragmentAction.CollectionExpanded(collection, expand))
|
||||
}
|
||||
|
||||
override fun handleonOpenNewTabClicked() {
|
||||
|
|
|
@ -12,7 +12,7 @@ import androidx.appcompat.content.res.AppCompatResources
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.tab_list_row.*
|
||||
import mozilla.components.feature.media.state.MediaState
|
||||
import mozilla.components.browser.state.state.MediaState
|
||||
import mozilla.components.support.ktx.android.util.dpToFloat
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
|
@ -50,15 +50,19 @@ class TabViewHolder(
|
|||
|
||||
play_pause_button.setOnClickListener {
|
||||
when (tab?.mediaState) {
|
||||
is MediaState.Playing -> {
|
||||
MediaState.State.PLAYING -> {
|
||||
it.context.components.analytics.metrics.track(Event.TabMediaPause)
|
||||
interactor.onPauseMediaClicked()
|
||||
}
|
||||
|
||||
is MediaState.Paused -> {
|
||||
MediaState.State.PAUSED -> {
|
||||
it.context.components.analytics.metrics.track(Event.TabMediaPlay)
|
||||
interactor.onPlayMediaClicked()
|
||||
}
|
||||
|
||||
MediaState.State.NONE -> throw AssertionError(
|
||||
"Play/Pause button clicked without play/pause state."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,20 +86,20 @@ class TabViewHolder(
|
|||
updateHostname(tab.hostname)
|
||||
updateFavIcon(tab.url, tab.icon)
|
||||
updateSelected(tab.selected ?: false)
|
||||
updatePlayPauseButton(tab.mediaState ?: MediaState.None)
|
||||
updatePlayPauseButton(tab.mediaState)
|
||||
item_tab.transitionName = "$TAB_ITEM_TRANSITION_NAME${tab.sessionId}"
|
||||
updateCloseButtonDescription(tab.title)
|
||||
}
|
||||
|
||||
internal fun updatePlayPauseButton(mediaState: MediaState) {
|
||||
internal fun updatePlayPauseButton(mediaState: MediaState.State) {
|
||||
with(play_pause_button) {
|
||||
visibility = if (mediaState is MediaState.Playing || mediaState is MediaState.Paused) {
|
||||
visibility = if (mediaState == MediaState.State.PLAYING || mediaState == MediaState.State.PAUSED) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
if (mediaState is MediaState.Playing) {
|
||||
if (mediaState == MediaState.State.PLAYING) {
|
||||
play_pause_button.contentDescription =
|
||||
context.getString(R.string.mozac_feature_media_notification_action_pause)
|
||||
setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.pause_with_background))
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/* 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.media
|
||||
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.feature.media.service.AbstractMediaService
|
||||
import org.mozilla.fenix.ext.components
|
||||
|
||||
/**
|
||||
* [AbstractMediaService] implementation for injecting [BrowserStore] singleton.
|
||||
*/
|
||||
class MediaService : AbstractMediaService() {
|
||||
override val store: BrowserStore by lazy { components.core.store }
|
||||
}
|
|
@ -19,6 +19,8 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi
|
|||
import kotlinx.coroutines.async
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.feature.tab.collections.Tab
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
import org.junit.Assert.assertEquals
|
||||
|
@ -44,6 +46,7 @@ class CollectionCreationFragmentTest {
|
|||
|
||||
@MockK private lateinit var sessionManager: SessionManager
|
||||
@MockK private lateinit var publicSuffixList: PublicSuffixList
|
||||
@MockK private lateinit var store: BrowserStore
|
||||
|
||||
private val sessionMozilla = Session(initialUrl = URL_MOZILLA, id = SESSION_ID_MOZILLA)
|
||||
private val sessionBcc = Session(initialUrl = URL_BCC, id = SESSION_ID_BCC)
|
||||
|
@ -57,6 +60,7 @@ class CollectionCreationFragmentTest {
|
|||
every { sessionManager.findSessionById(SESSION_ID_BAD_2) } answers { null }
|
||||
every { publicSuffixList.stripPublicSuffix(URL_MOZILLA) } answers { GlobalScope.async { URL_MOZILLA } }
|
||||
every { publicSuffixList.stripPublicSuffix(URL_BCC) } answers { GlobalScope.async { URL_BCC } }
|
||||
every { store.state } answers { BrowserState() }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -80,7 +84,7 @@ class CollectionCreationFragmentTest {
|
|||
@Test
|
||||
fun `GIVEN tabs are present in session manager WHEN getTabs is called THEN tabs will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BCC), publicSuffixList)
|
||||
.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BCC), store, publicSuffixList)
|
||||
|
||||
val hosts = tabs.map { it.hostname }
|
||||
|
||||
|
@ -91,7 +95,7 @@ class CollectionCreationFragmentTest {
|
|||
@Test
|
||||
fun `GIVEN some tabs are present in session manager WHEN getTabs is called THEN only valid tabs will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BAD_1), publicSuffixList)
|
||||
.getTabs(arrayOf(SESSION_ID_MOZILLA, SESSION_ID_BAD_1), store, publicSuffixList)
|
||||
|
||||
val hosts = tabs.map { it.hostname }
|
||||
|
||||
|
@ -102,7 +106,7 @@ class CollectionCreationFragmentTest {
|
|||
@Test
|
||||
fun `GIVEN tabs are not present in session manager WHEN getTabs is called THEN an empty list will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(arrayOf(SESSION_ID_BAD_1, SESSION_ID_BAD_2), publicSuffixList)
|
||||
.getTabs(arrayOf(SESSION_ID_BAD_1, SESSION_ID_BAD_2), store, publicSuffixList)
|
||||
|
||||
assertEquals(emptyList<Tab>(), tabs)
|
||||
}
|
||||
|
@ -110,7 +114,7 @@ class CollectionCreationFragmentTest {
|
|||
@Test
|
||||
fun `WHEN getTabs is called will null tabIds THEN an empty list will be returned`() {
|
||||
val tabs = sessionManager
|
||||
.getTabs(null, publicSuffixList)
|
||||
.getTabs(null, store, publicSuffixList)
|
||||
|
||||
assertEquals(emptyList<Tab>(), tabs)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import kotlinx.coroutines.newSingleThreadContext
|
|||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.Engine
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.tabs.TabsUseCases
|
||||
|
@ -38,8 +39,9 @@ import mozilla.components.feature.tab.collections.Tab as ComponentTab
|
|||
class DefaultSessionControlControllerTest {
|
||||
|
||||
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
|
||||
private val store: BrowserStore = mockk(relaxed = true)
|
||||
private val activity: HomeActivity = mockk(relaxed = true)
|
||||
private val store: HomeFragmentStore = mockk(relaxed = true)
|
||||
private val fragmentStore: HomeFragmentStore = mockk(relaxed = true)
|
||||
private val navController: NavController = mockk(relaxed = true)
|
||||
private val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
|
||||
private val closeTab: (sessionId: String) -> Unit = mockk(relaxed = true)
|
||||
|
@ -71,7 +73,7 @@ class DefaultSessionControlControllerTest {
|
|||
every { activity.components.core.tabCollectionStorage } returns tabCollectionStorage
|
||||
every { activity.components.useCases.tabsUseCases } returns tabsUseCases
|
||||
|
||||
every { store.state } returns state
|
||||
every { fragmentStore.state } returns state
|
||||
every { state.collections } returns emptyList()
|
||||
every { state.expandedCollections } returns emptySet()
|
||||
every { state.mode } returns Mode.Normal
|
||||
|
@ -79,8 +81,9 @@ class DefaultSessionControlControllerTest {
|
|||
every { activity.components.analytics.metrics } returns metrics
|
||||
|
||||
controller = DefaultSessionControlController(
|
||||
activity = activity,
|
||||
store = store,
|
||||
activity = activity,
|
||||
fragmentStore = fragmentStore,
|
||||
navController = navController,
|
||||
browsingModeManager = browsingModeManager,
|
||||
lifecycleScope = MainScope(),
|
||||
|
@ -235,6 +238,6 @@ class DefaultSessionControlControllerTest {
|
|||
fun handleToggleCollectionExpanded() {
|
||||
val collection: TabCollection = mockk(relaxed = true)
|
||||
controller.handleToggleCollectionExpanded(collection, true)
|
||||
verify { store.dispatch(HomeFragmentAction.CollectionExpanded(collection, true)) }
|
||||
verify { fragmentStore.dispatch(HomeFragmentAction.CollectionExpanded(collection, true)) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
object AndroidComponents {
|
||||
const val VERSION = "38.0.20200326160141"
|
||||
const val VERSION = "38.0.20200327101347"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue