From 346b4aa3fdf64812a1a9dfa27bce01d758ab4974 Mon Sep 17 00:00:00 2001 From: David Walsh Date: Wed, 20 May 2020 16:50:58 -0500 Subject: [PATCH] For #10321: Wire up play and pause buttons in tab tray (#10422) --- .../java/org/mozilla/fenix/HomeActivity.kt | 12 +- .../fenix/tabtray/TabTrayViewHolder.kt | 160 ++++++++++++++++++ .../tab_tray_pause_with_background.xml | 30 ++++ .../tab_tray_play_with_background.xml | 30 ++++ app/src/main/res/layout/fragment_tab_tray.xml | 8 +- app/src/main/res/layout/tab_tray_item.xml | 17 ++ app/src/main/res/values-night/colors.xml | 1 + app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/styles.xml | 2 + 10 files changed, 252 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/tabtray/TabTrayViewHolder.kt create mode 100644 app/src/main/res/drawable/tab_tray_pause_with_background.xml create mode 100644 app/src/main/res/drawable/tab_tray_play_with_background.xml diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 8fd735974..a3a7553a3 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -80,8 +80,8 @@ import org.mozilla.fenix.utils.RunWhenReadyQueue import mozilla.components.concept.tabstray.TabsTray import mozilla.components.browser.tabstray.TabsAdapter import mozilla.components.browser.tabstray.BrowserTabsTray -import mozilla.components.browser.tabstray.DefaultTabViewHolder import org.mozilla.fenix.tabtray.TabTrayFragmentDirections +import org.mozilla.fenix.tabtray.TabTrayViewHolder /** * The main activity of the application. The application is primarily a single Activity (this one) @@ -222,14 +222,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity() { }.asView() TabsTray::class.java.name -> { val layout = LinearLayoutManager(context) - val adapter = TabsAdapter { parentView, tabsTray -> - - DefaultTabViewHolder( - LayoutInflater.from(parentView.context).inflate( + val adapter = TabsAdapter { parentView, _ -> + TabTrayViewHolder( + LayoutInflater.from(this).inflate( R.layout.tab_tray_item, parentView, - false), - tabsTray + false) ) } val decoration = DividerItemDecoration( diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayViewHolder.kt new file mode 100644 index 000000000..df4d7fdf0 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayViewHolder.kt @@ -0,0 +1,160 @@ +/* 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.tabtray + +import android.view.View +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import androidx.appcompat.widget.AppCompatImageButton +import androidx.core.content.ContextCompat +import mozilla.components.browser.state.state.MediaState +import mozilla.components.browser.tabstray.TabViewHolder +import mozilla.components.browser.tabstray.thumbnail.TabThumbnailView +import mozilla.components.concept.tabstray.Tab +import mozilla.components.concept.tabstray.TabsTray +import mozilla.components.feature.media.ext.pauseIfPlaying +import mozilla.components.feature.media.ext.playIfPaused +import mozilla.components.support.base.observer.Observable +import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl +import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.increaseTapArea +import org.mozilla.fenix.ext.removeAndDisable +import org.mozilla.fenix.ext.removeTouchDelegate +import org.mozilla.fenix.ext.showAndEnable +import org.mozilla.fenix.ext.toTab +import org.mozilla.fenix.theme.ThemeManager + +/** + * A RecyclerView ViewHolder implementation for "tab" items. + */ +class TabTrayViewHolder(itemView: View) : TabViewHolder(itemView) { + private val iconView: ImageView? = itemView.findViewById(R.id.mozac_browser_tabstray_icon) + private val titleView: TextView = itemView.findViewById(R.id.mozac_browser_tabstray_title) + private val closeView: AppCompatImageButton = itemView.findViewById(R.id.mozac_browser_tabstray_close) + private val thumbnailView: TabThumbnailView = itemView.findViewById(R.id.mozac_browser_tabstray_thumbnail) + private val urlView: TextView? = itemView.findViewById(R.id.mozac_browser_tabstray_url) + private val playPauseButtonView: ImageButton = itemView.findViewById(R.id.play_pause_button) + + override var tab: Tab? = null + + /** + * Displays the data of the given session and notifies the given observable about events. + */ + override fun bind(tab: Tab, isSelected: Boolean, observable: Observable) { + this.tab = tab + + // Basic text + updateTitle(tab) + updateUrl(tab) + updateCloseButtonDescription(tab.title) + + // Drawables and theme + updateBackgroundColor(isSelected) + thumbnailView.setImageBitmap(tab.thumbnail) + iconView?.setImageBitmap(tab.icon) + + // Media state + playPauseButtonView.increaseTapArea(PLAY_PAUSE_BUTTON_EXTRA_DPS) + val session = itemView.context?.components?.core?.sessionManager?.findSessionById(tab.id) + with(playPauseButtonView) { + invalidate() + when (session?.toTab(itemView.context)?.mediaState) { + MediaState.State.PAUSED -> { + showAndEnable() + contentDescription = + context.getString(R.string.mozac_feature_media_notification_action_play) + setImageDrawable( + androidx.appcompat.content.res.AppCompatResources.getDrawable( + context, + R.drawable.tab_tray_play_with_background + ) + ) + } + + MediaState.State.PLAYING -> { + showAndEnable() + contentDescription = + context.getString(R.string.mozac_feature_media_notification_action_pause) + setImageDrawable( + androidx.appcompat.content.res.AppCompatResources.getDrawable( + context, + R.drawable.tab_tray_pause_with_background + ) + ) + } + + MediaState.State.NONE -> { + removeTouchDelegate() + removeAndDisable() + } + } + } + + playPauseButtonView.setOnClickListener { + val mState = session?.toTab(itemView.context)?.mediaState + when (mState) { + MediaState.State.PLAYING -> { + itemView.context.components.analytics.metrics.track(Event.TabMediaPause) + itemView.context.components.core.store.state.media.pauseIfPlaying() + } + + MediaState.State.PAUSED -> { + itemView.context.components.analytics.metrics.track(Event.TabMediaPlay) + itemView.context.components.core.store.state.media.playIfPaused() + } + + MediaState.State.NONE -> throw AssertionError( + "Play/Pause button clicked without play/pause state." + ) + } + } + + itemView.setOnClickListener { + observable.notifyObservers { onTabSelected(tab) } + } + + closeView.setOnClickListener { + observable.notifyObservers { onTabClosed(tab) } + } + } + + private fun updateTitle(tab: Tab) { + val title = if (tab.title.isNotEmpty()) { + tab.title + } else { + tab.url + } + titleView.text = title + } + private fun updateUrl(tab: Tab) { + urlView?.text = tab.url.tryGetHostFromUrl() + } + + private fun updateBackgroundColor(isSelected: Boolean) { + val itemBackground = if (isSelected) { + R.attr.tabTrayItemSelectedBackground + } else { + R.attr.tabTrayItemBackground + } + itemView.setBackgroundColor( + ContextCompat.getColor( + itemView.context, + ThemeManager.resolveAttribute(itemBackground, itemView.context) + ) + ) + } + + private fun updateCloseButtonDescription(title: String) { + closeView.contentDescription = + closeView.context.getString(R.string.close_tab_title, title) + } + + companion object { + private const val PLAY_PAUSE_BUTTON_EXTRA_DPS = 24 + } +} diff --git a/app/src/main/res/drawable/tab_tray_pause_with_background.xml b/app/src/main/res/drawable/tab_tray_pause_with_background.xml new file mode 100644 index 000000000..337bf611d --- /dev/null +++ b/app/src/main/res/drawable/tab_tray_pause_with_background.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/tab_tray_play_with_background.xml b/app/src/main/res/drawable/tab_tray_play_with_background.xml new file mode 100644 index 000000000..3694d4c3c --- /dev/null +++ b/app/src/main/res/drawable/tab_tray_play_with_background.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_tab_tray.xml b/app/src/main/res/layout/fragment_tab_tray.xml index 6f77a32f0..3fa747a42 100644 --- a/app/src/main/res/layout/fragment_tab_tray.xml +++ b/app/src/main/res/layout/fragment_tab_tray.xml @@ -34,13 +34,7 @@ app:layout_constraintBottom_toTopOf="@+id/save_to_collection_button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - mozac:tabsTrayItemBackgroundColor="?tabTrayItemBackground" - mozac:tabsTrayItemTextColor="?tabTrayItemText" - mozac:tabsTraySelectedItemBackgroundColor="?tabTrayItemSelectedBackground" - mozac:tabsTraySelectedItemTextColor="?tabTrayItemText" - mozac:tabsTrayItemUrlTextColor="?tabTrayItemUrl" - mozac:tabsTraySelectedItemUrlTextColor="?tabTrayItemUrl"/> + app:layout_constraintTop_toTopOf="parent" /> + + diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 5b3c13015..bab591fcf 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -52,6 +52,7 @@ @color/tab_tray_item_selected_background_dark_theme @color/tab_tray_toolbar_background_dark_theme @color/tab_tray_item_divider_dark_theme + @color/tab_tray_item_media_background_dark_theme @color/collection_icon_color_violet_dark_theme diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index f7ad4e5b6..1a2dc014f 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -57,6 +57,7 @@ + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7877c37ac..b98801607 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -66,6 +66,8 @@ @color/violet_70_12a @color/light_grey_10 @color/light_grey_30 + #ffffff + #312A65 #FBFBFE @@ -115,6 +117,7 @@ @color/violet_50_32a @color/dark_grey_50 @color/dark_grey_10 + #9059FF #FBFBFE @@ -163,6 +166,7 @@ @color/violet_50_32a @color/ink_50 @color/dark_grey_10 + #9059FF @color/primary_text_light_theme @@ -210,6 +214,7 @@ @color/tab_tray_item_selected_background_light_theme @color/tab_tray_toolbar_background_light_theme @color/tab_tray_item_divider_light_theme + @color/tab_tray_item_media_background_light_theme #DFDFE3 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 764bb6bb0..a3ca26dc6 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -79,6 +79,7 @@ @color/tab_tray_item_selected_background_normal_theme @color/tab_tray_toolbar_background_normal_theme @color/tab_tray_item_divider_normal_theme + @color/tab_tray_item_media_background_normal_theme @drawable/ic_logo_wordmark_normal @@ -203,6 +204,7 @@ @color/tab_tray_item_selected_background_private_theme @color/tab_tray_toolbar_background_private_theme @color/tab_tray_item_divider_private_theme + @color/tab_tray_item_media_background_private_theme @drawable/ic_logo_wordmark_private