Merge pull request #1226 from prathameshmm02/dev
New features, improvements and bug fixes
This commit is contained in:
commit
b74b4808c6
328 changed files with 3803 additions and 26387 deletions
|
@ -14,8 +14,8 @@ android {
|
|||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
applicationId "code.name.monkey.retromusic"
|
||||
versionCode 10557
|
||||
versionName '5.6.1'
|
||||
versionCode 10563
|
||||
versionName '5.7.0'
|
||||
|
||||
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
|
||||
}
|
||||
|
@ -88,14 +88,13 @@ static def getDate() {
|
|||
new Date().format('MMddyyyyss')
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation project(':appthemehelper')
|
||||
implementation "androidx.gridlayout:gridlayout:1.0.0"
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||
implementation 'androidx.annotation:annotation:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-alpha01'
|
||||
implementation "androidx.preference:preference-ktx:$preference_version"
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
|
@ -103,7 +102,7 @@ dependencies {
|
|||
|
||||
//Cast Dependencies
|
||||
implementation 'androidx.mediarouter:mediarouter:1.2.5'
|
||||
implementation 'com.google.android.gms:play-services-cast-framework:21.0.0'
|
||||
implementation 'com.google.android.gms:play-services-cast-framework:21.0.1'
|
||||
//WebServer by NanoHttpd
|
||||
implementation "org.nanohttpd:nanohttpd:2.3.1"
|
||||
|
||||
|
@ -111,7 +110,7 @@ dependencies {
|
|||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
||||
|
||||
def room_version = '2.4.0'
|
||||
def room_version = '2.4.1'
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
implementation "androidx.room:room-ktx:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
|
@ -143,7 +142,7 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
|
||||
def koin_version = '3.1.4'
|
||||
def koin_version = '3.1.5'
|
||||
implementation "io.insert-koin:koin-core:$koin_version"
|
||||
implementation "io.insert-koin:koin-android:$koin_version"
|
||||
|
||||
|
@ -160,6 +159,8 @@ dependencies {
|
|||
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC3'
|
||||
implementation 'com.github.jetradarmobile:android-snowfall:1.2.1'
|
||||
|
||||
implementation "dev.chrisbanes.insetter:insetter:0.6.1"
|
||||
|
||||
implementation 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5'
|
||||
implementation 'com.github.Adonai:jaudiotagger:2.3.15'
|
||||
implementation 'com.anjlab.android.iab.v3:library:2.0.3'
|
||||
|
|
|
@ -292,6 +292,18 @@
|
|||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/app_widget_md3_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".appwidgets.AppWidgetCircle"
|
||||
android:exported="true"
|
||||
android:label="@string/app_widget_circle_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/app_widget_circle_info" />
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".service.MusicService"
|
||||
|
|
|
@ -70,6 +70,8 @@
|
|||
title="KeyboardVisibilityEvent">KeyboardVisibilityEvent</a></b> by Yasuhiro SHIMIZU</p>
|
||||
<p><b><a href="https://github.com/JetradarMobile/android-snowfall"
|
||||
title="android-snowfall">android-snowfall</a></b> by Jetradar Mobile</p>
|
||||
<p><b><a href="https://github.com/chrisbanes/insetter"
|
||||
title="Insetter">Insetter</a></b> by Chris Banes</p>
|
||||
<p><b><a href="https://materialdesignicons.com" title="Icons"> Icons</a></b> by Austin Andrews</p>
|
||||
<p><b><a href="https://www.techjuice.pk" title="City wallpaper"> Material Design City Wallpaper</a></b>
|
||||
</p>
|
||||
|
|
|
@ -58,12 +58,41 @@
|
|||
}
|
||||
|
||||
{style-placeholder}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h5>December 28, 2021</h5>
|
||||
<h5>January 25, 2022</h5>
|
||||
<h2>v5.7.0</h2>
|
||||
<h3>What's New</h3>
|
||||
<ul>
|
||||
<li>Added accent color extraction on Android 8.1+ devices</li>
|
||||
<li>Added new Circle widget</li>
|
||||
<li>Added Collapsing appbar to library tabs with an option to switch back to simple appbar
|
||||
</li>
|
||||
<li>Added Search tab</li>
|
||||
<li>Added option to use circular play button</li>
|
||||
<li>Added lyrics editing on A11+ devices again</li>
|
||||
<li>Added Long Press to forward, rewind current song</li>
|
||||
<li>Added ability to set Playback speed and pitch</li>
|
||||
<li>Added option to show lyrics over Cover</li>
|
||||
<li>Added option to keep screen on when showing lyrics</li>
|
||||
<li>Added option to switch to Manrope font</li>
|
||||
</ul>
|
||||
<h3>Fixed</h3>
|
||||
<ul>
|
||||
<li>Fixed Gapless Playback</li>
|
||||
<li>Fixed Shuffle FAB going behind Mini Player</li>
|
||||
<li>Fixed crashes on Pre-marshmallow devices</li>
|
||||
<li>Blacklisted songs can't be played after opening from outside the app</li>
|
||||
<li>Fixed various small bugs and some minor improvements</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h5>January 1, 2021</h5>
|
||||
<h2>v5.6.1</h2>
|
||||
<h3>Fixed</h3>
|
||||
<ul>
|
||||
|
|
|
@ -20,6 +20,7 @@ import code.name.monkey.appthemehelper.ThemeStore
|
|||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||
import code.name.monkey.retromusic.helper.WallpaperAccentManager
|
||||
import com.anjlab.android.iab.v3.BillingProcessor
|
||||
import com.anjlab.android.iab.v3.PurchaseInfo
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
|
@ -28,6 +29,7 @@ import org.koin.core.context.startKoin
|
|||
class App : Application() {
|
||||
|
||||
lateinit var billingProcessor: BillingProcessor
|
||||
private val wallpaperAccentManager = WallpaperAccentManager(this)
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
@ -44,6 +46,7 @@ class App : Application() {
|
|||
.coloredNavigationBar(true)
|
||||
.commit()
|
||||
}
|
||||
wallpaperAccentManager.init()
|
||||
|
||||
if (VersionUtils.hasNougatMR())
|
||||
DynamicShortcutManager(this).initDynamicShortcuts()
|
||||
|
@ -71,6 +74,7 @@ class App : Application() {
|
|||
override fun onTerminate() {
|
||||
super.onTerminate()
|
||||
billingProcessor.release()
|
||||
wallpaperAccentManager.release()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -73,7 +73,7 @@ const val NOW_PLAYING_SCREEN_ID = "now_playing_screen_id"
|
|||
const val CAROUSEL_EFFECT = "carousel_effect"
|
||||
const val COLORED_NOTIFICATION = "colored_notification"
|
||||
const val CLASSIC_NOTIFICATION = "classic_notification"
|
||||
const val GAP_LESS_PLAYBACK = "gap_less_playback"
|
||||
const val GAP_LESS_PLAYBACK = "gapless_playback"
|
||||
const val ALBUM_ART_ON_LOCK_SCREEN = "album_art_on_lock_screen"
|
||||
const val BLURRED_ALBUM_ART = "blurred_album_art"
|
||||
const val NEW_BLUR_AMOUNT = "new_blur_amount"
|
||||
|
@ -154,3 +154,11 @@ const val LAST_USED_TAB = "last_used_tab"
|
|||
const val WHITELIST_MUSIC = "whitelist_music"
|
||||
const val MATERIAL_YOU = "material_you"
|
||||
const val SNOWFALL = "snowfall"
|
||||
const val LYRICS_TYPE = "lyrics_type"
|
||||
const val PLAYBACK_SPEED = "playback_speed"
|
||||
const val PLAYBACK_PITCH = "playback_pitch"
|
||||
const val CUSTOM_FONT = "custom_font"
|
||||
const val APPBAR_MODE = "appbar_mode"
|
||||
const val WALLPAPER_ACCENT = "wallpaper_accent"
|
||||
const val SCREEN_ON_LYRICS = "screen_on_lyrics"
|
||||
const val CIRCLE_PLAY_BUTTON = "circle_play_button"
|
|
@ -62,7 +62,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
|||
if (!hasPermissions()) {
|
||||
findNavController(R.id.fragment_container).navigate(R.id.permissionFragment)
|
||||
}
|
||||
if (BuildConfig.VERSION_CODE > PreferenceUtil.lastVersion && !BuildConfig.DEBUG){
|
||||
if (BuildConfig.VERSION_CODE > PreferenceUtil.lastVersion && !BuildConfig.DEBUG) {
|
||||
NavigationUtil.gotoWhatNews(this)
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
|||
currentFragment(R.id.fragment_container)?.enterTransition = null
|
||||
}
|
||||
when (destination.id) {
|
||||
R.id.action_home, R.id.action_song, R.id.action_album, R.id.action_artist, R.id.action_folder, R.id.action_playlist, R.id.action_genre -> {
|
||||
R.id.action_home, R.id.action_song, R.id.action_album, R.id.action_artist, R.id.action_folder, R.id.action_playlist, R.id.action_genre, R.id.action_search -> {
|
||||
// Save the last tab
|
||||
if (PreferenceUtil.rememberLastTab) {
|
||||
saveTab(destination.id)
|
||||
|
@ -147,7 +147,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
|||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
if (key == GENERAL_THEME || key == MATERIAL_YOU || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES) {
|
||||
if (key == GENERAL_THEME || key == MATERIAL_YOU || key == WALLPAPER_ACCENT || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES || key == CUSTOM_FONT || key == APPBAR_MODE || key == CIRCLE_PLAY_BUTTON) {
|
||||
postRecreate()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,9 @@ import android.os.Bundle
|
|||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
|
@ -37,6 +34,7 @@ import code.name.monkey.retromusic.BuildConfig
|
|||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||
import code.name.monkey.retromusic.databinding.ActivityDonationBinding
|
||||
import code.name.monkey.retromusic.databinding.ItemDonationOptionBinding
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import com.anjlab.android.iab.v3.BillingProcessor
|
||||
import com.anjlab.android.iab.v3.PurchaseInfo
|
||||
|
@ -169,8 +167,8 @@ class SkuDetailsAdapter(
|
|||
|
||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder {
|
||||
return ViewHolder(
|
||||
LayoutInflater.from(donationsDialog).inflate(
|
||||
LAYOUT_RES_ID,
|
||||
ItemDonationOptionBinding.inflate(
|
||||
LayoutInflater.from(donationsDialog),
|
||||
viewGroup,
|
||||
false
|
||||
)
|
||||
|
@ -179,12 +177,14 @@ class SkuDetailsAdapter(
|
|||
|
||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
|
||||
val skuDetails = skuDetailsList[i]
|
||||
viewHolder.title.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "")
|
||||
with(viewHolder.binding) {
|
||||
itemTitle.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "")
|
||||
.trim { it <= ' ' }
|
||||
viewHolder.text.text = skuDetails.description
|
||||
viewHolder.text.isVisible = false
|
||||
viewHolder.price.text = skuDetails.priceText
|
||||
viewHolder.image.setImageResource(getIcon(i))
|
||||
itemText.text = skuDetails.description
|
||||
itemText.isVisible = false
|
||||
itemPrice.text = skuDetails.priceText
|
||||
itemImage.setImageResource(getIcon(i))
|
||||
}
|
||||
|
||||
val purchased = donationsDialog.billingProcessor!!.isPurchased(skuDetails.productId)
|
||||
val titleTextColor = if (purchased) ATHUtil.resolveColor(
|
||||
|
@ -194,13 +194,14 @@ class SkuDetailsAdapter(
|
|||
val contentTextColor =
|
||||
if (purchased) titleTextColor else donationsDialog.textColorSecondary()
|
||||
|
||||
viewHolder.title.setTextColor(titleTextColor)
|
||||
viewHolder.text.setTextColor(contentTextColor)
|
||||
viewHolder.price.setTextColor(titleTextColor)
|
||||
|
||||
strikeThrough(viewHolder.title, purchased)
|
||||
strikeThrough(viewHolder.text, purchased)
|
||||
strikeThrough(viewHolder.price, purchased)
|
||||
with(viewHolder.binding) {
|
||||
itemTitle.setTextColor(titleTextColor)
|
||||
itemText.setTextColor(contentTextColor)
|
||||
itemPrice.setTextColor(titleTextColor)
|
||||
strikeThrough(itemTitle, purchased)
|
||||
strikeThrough(itemText, purchased)
|
||||
strikeThrough(itemPrice, purchased)
|
||||
}
|
||||
|
||||
viewHolder.itemView.setOnTouchListener { _, _ -> purchased }
|
||||
viewHolder.itemView.setOnClickListener { donationsDialog.donate(i) }
|
||||
|
@ -210,17 +211,9 @@ class SkuDetailsAdapter(
|
|||
return skuDetailsList.size
|
||||
}
|
||||
|
||||
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
var title: TextView = view.findViewById(R.id.itemTitle)
|
||||
var text: TextView = view.findViewById(R.id.itemText)
|
||||
var price: TextView = view.findViewById(R.id.itemPrice)
|
||||
var image: AppCompatImageView = view.findViewById(R.id.itemImage)
|
||||
}
|
||||
class ViewHolder(val binding: ItemDonationOptionBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
@LayoutRes
|
||||
private val LAYOUT_RES_ID = R.layout.item_donation_option
|
||||
|
||||
private fun strikeThrough(textView: TextView, strikeThrough: Boolean) {
|
||||
textView.paintFlags =
|
||||
if (strikeThrough) textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||
|
|
|
@ -27,7 +27,6 @@ class WhatsNewActivity : AbsThemeActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
val binding = ActivityWhatsNewBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setLightStatusBarAuto(surfaceColor())
|
||||
setTaskDescriptionColorAuto()
|
||||
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
||||
|
|
|
@ -31,7 +31,7 @@ import androidx.core.view.isGone
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.commit
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.RetroBottomSheetBehavior
|
||||
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
|
||||
|
@ -110,9 +110,15 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
when (newState) {
|
||||
STATE_EXPANDED -> {
|
||||
onPanelExpanded()
|
||||
if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) {
|
||||
keepScreenOn(true)
|
||||
}
|
||||
}
|
||||
STATE_COLLAPSED -> {
|
||||
onPanelCollapsed()
|
||||
if ((PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) || !PreferenceUtil.isScreenOnEnabled) {
|
||||
keepScreenOn(false)
|
||||
}
|
||||
}
|
||||
STATE_SETTLING, STATE_DRAGGING -> {
|
||||
if (fromNotification) {
|
||||
|
@ -140,7 +146,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
insets
|
||||
}
|
||||
if (RetroUtil.isLandscape()) {
|
||||
binding.slidingPanel.drawAboveSystemBarsWithPadding(true)
|
||||
binding.slidingPanel.drawAboveSystemBarsWithPadding()
|
||||
}
|
||||
chooseFragmentForTheme()
|
||||
setupSlidingUpPanel()
|
||||
|
@ -199,6 +205,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
}
|
||||
|
||||
private fun animateNavigationBarColor(color: Int) {
|
||||
if (VersionUtils.hasOreo()) return
|
||||
navigationBarColorAnimator?.cancel()
|
||||
navigationBarColorAnimator = ValueAnimator
|
||||
.ofArgb(window.navigationBarColor, color).apply {
|
||||
|
@ -217,14 +224,16 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
setMiniPlayerAlphaProgress(0F)
|
||||
// restore values
|
||||
animateNavigationBarColor(surfaceColor())
|
||||
setLightStatusBarAuto(surfaceColor())
|
||||
setLightNavigationAuto()
|
||||
setLightStatusBarAuto()
|
||||
setLightNavigationBarAuto()
|
||||
setTaskDescriptionColor(taskColor)
|
||||
playerFragment?.onHide()
|
||||
}
|
||||
|
||||
open fun onPanelExpanded() {
|
||||
setMiniPlayerAlphaProgress(1F)
|
||||
onPaletteColorChanged()
|
||||
playerFragment?.onShow()
|
||||
}
|
||||
|
||||
private fun setupSlidingUpPanel() {
|
||||
|
@ -291,7 +300,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
if (panelState == STATE_EXPANDED) {
|
||||
navigationBarColor = surfaceColor()
|
||||
setTaskDescColor(paletteColor)
|
||||
val isColorLight = ColorUtil.isColorLight(paletteColor)
|
||||
val isColorLight = paletteColor.isColorLight
|
||||
if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat)) {
|
||||
setLightNavigationBar(true)
|
||||
setLightStatusBar(isColorLight)
|
||||
|
@ -314,13 +323,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
setLightStatusBar(false)
|
||||
} else if (nowPlayingScreen == Fit) {
|
||||
setLightStatusBar(false)
|
||||
} else {
|
||||
setLightStatusBar(
|
||||
ColorUtil.isColorLight(
|
||||
surfaceColor()
|
||||
)
|
||||
)
|
||||
setLightNavigationBar(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -401,12 +403,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
|
||||
bottomSheetBehavior.state = STATE_COLLAPSED
|
||||
libraryViewModel.setFabMargin(if (isBottomNavVisible) dip(R.dimen.bottom_nav_height) else 0)
|
||||
binding.slidingPanel.elevation = 0F
|
||||
binding.bottomNavigationView.elevation = 10F
|
||||
} else {
|
||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||
binding.slidingPanel.elevation = 0F
|
||||
binding.bottomNavigationView.elevation = 10F
|
||||
binding.bottomNavigationView.elevation = 5F
|
||||
if (isBottomNavVisible) {
|
||||
println("List")
|
||||
if (animate) {
|
||||
|
|
|
@ -23,11 +23,12 @@ import android.view.View
|
|||
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.LanguageContextWrapper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.theme.ThemeManager
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import java.util.*
|
||||
|
||||
abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||
|
@ -35,27 +36,28 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
|||
private val handler = Handler()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setDrawBehindSystemBars()
|
||||
updateTheme()
|
||||
hideStatusBar()
|
||||
super.onCreate(savedInstanceState)
|
||||
setImmersiveFullscreen()
|
||||
setEdgeToEdgeOrImmersive()
|
||||
registerSystemUiVisibility()
|
||||
toggleScreenOn()
|
||||
setLightNavigationAuto()
|
||||
setLightNavigationBarAuto()
|
||||
setLightStatusBarAuto(surfaceColor())
|
||||
if (VersionUtils.hasQ()) {
|
||||
window.decorView.isForceDarkAllowed = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTheme() {
|
||||
setTheme(ThemeManager.getThemeResValue(this))
|
||||
setDefaultNightMode(ThemeManager.getNightMode(this))
|
||||
setTheme(ThemeManager.getThemeResValue())
|
||||
setDefaultNightMode(ThemeManager.getNightMode())
|
||||
|
||||
// Apply dynamic colors to activity if enabled
|
||||
if (PreferenceUtil.materialYou) {
|
||||
DynamicColors.applyIfAvailable(
|
||||
this,
|
||||
com.google.android.material.R.style.ThemeOverlay_Material3_DynamicColors_DayNight
|
||||
)
|
||||
if (PreferenceUtil.isCustomFont) {
|
||||
setTheme(R.style.FontThemeOverlay)
|
||||
}
|
||||
if (PreferenceUtil.circlePlayButton) {
|
||||
setTheme(R.style.CircleFABOverlay)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,11 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.adapter
|
||||
|
||||
import android.os.SystemClock
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.os.bundleOf
|
||||
|
@ -29,31 +28,22 @@ import androidx.navigation.fragment.FragmentNavigatorExtras
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.retromusic.*
|
||||
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
|
||||
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
|
||||
import code.name.monkey.retromusic.adapter.song.SongAdapter
|
||||
import code.name.monkey.retromusic.extensions.hide
|
||||
import code.name.monkey.retromusic.fragments.home.HomeFragment
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.IAlbumClickListener
|
||||
import code.name.monkey.retromusic.interfaces.IArtistClickListener
|
||||
import code.name.monkey.retromusic.interfaces.IGenreClickListener
|
||||
import code.name.monkey.retromusic.model.*
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
|
||||
class HomeAdapter(
|
||||
private val activity: AppCompatActivity
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener,
|
||||
IGenreClickListener {
|
||||
|
||||
private var mLastClickTime: Long = 0
|
||||
|
||||
private var list = listOf<Home>()
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
|
@ -65,17 +55,10 @@ class HomeAdapter(
|
|||
LayoutInflater.from(activity).inflate(R.layout.section_recycler_view, parent, false)
|
||||
return when (viewType) {
|
||||
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout)
|
||||
GENRES -> GenreViewHolder(layout)
|
||||
FAVOURITES -> PlaylistViewHolder(layout)
|
||||
TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(layout)
|
||||
else -> {
|
||||
SuggestionsViewHolder(
|
||||
LayoutInflater.from(activity).inflate(
|
||||
R.layout.item_suggestions,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
ArtistViewHolder(layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,10 +110,6 @@ class HomeAdapter(
|
|||
)
|
||||
}
|
||||
}
|
||||
SUGGESTIONS -> {
|
||||
val viewHolder = holder as SuggestionsViewHolder
|
||||
viewHolder.bindView(home)
|
||||
}
|
||||
FAVOURITES -> {
|
||||
val viewHolder = holder as PlaylistViewHolder
|
||||
viewHolder.bindView(home)
|
||||
|
@ -142,12 +121,6 @@ class HomeAdapter(
|
|||
)
|
||||
}
|
||||
}
|
||||
GENRES -> {
|
||||
val viewHolder = holder as GenreViewHolder
|
||||
viewHolder.bind(home)
|
||||
}
|
||||
PLAYLISTS -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,6 +128,7 @@ class HomeAdapter(
|
|||
return list.size
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun swapData(sections: List<Home>) {
|
||||
list = sections
|
||||
notifyDataSetChanged()
|
||||
|
@ -180,52 +154,6 @@ class HomeAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
private inner class SuggestionsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val images = listOf(
|
||||
R.id.image1,
|
||||
R.id.image2,
|
||||
R.id.image3,
|
||||
R.id.image4,
|
||||
R.id.image5,
|
||||
R.id.image6,
|
||||
R.id.image7,
|
||||
R.id.image8
|
||||
)
|
||||
|
||||
fun bindView(home: Home) {
|
||||
val color = ThemeStore.accentColor(activity)
|
||||
itemView.findViewById<TextView>(R.id.message).apply {
|
||||
setTextColor(color)
|
||||
setOnClickListener {
|
||||
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000){
|
||||
return@setOnClickListener
|
||||
}
|
||||
mLastClickTime = SystemClock.elapsedRealtime()
|
||||
MusicPlayerRemote.playNext((home.arrayList as List<Song>).subList(0, 8))
|
||||
if (!MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
}
|
||||
}
|
||||
}
|
||||
itemView.findViewById<MaterialCardView>(R.id.card6).apply {
|
||||
setCardBackgroundColor(ColorUtil.withAlpha(color, 0.12f))
|
||||
}
|
||||
images.forEachIndexed { index, id ->
|
||||
itemView.findViewById<View>(id).setOnClickListener {
|
||||
MusicPlayerRemote.playNext(home.arrayList[index] as Song)
|
||||
if (!MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
}
|
||||
}
|
||||
GlideApp.with(activity)
|
||||
.asBitmap()
|
||||
.songCoverOptions(home.arrayList[index] as Song)
|
||||
.load(RetroGlideExtension.getSongModel(home.arrayList[index] as Song))
|
||||
.into(itemView.findViewById(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
|
||||
fun bindView(home: Home) {
|
||||
title.setText(home.titleRes)
|
||||
|
@ -241,22 +169,6 @@ class HomeAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
private inner class GenreViewHolder(itemView: View) : AbsHomeViewItem(itemView) {
|
||||
fun bind(home: Home) {
|
||||
arrow.hide()
|
||||
title.setText(home.titleRes)
|
||||
val genreAdapter = GenreAdapter(
|
||||
activity,
|
||||
home.arrayList as List<Genre>,
|
||||
this@HomeAdapter
|
||||
)
|
||||
recyclerView.apply {
|
||||
layoutManager = GridLayoutManager(activity, 3, GridLayoutManager.HORIZONTAL, false)
|
||||
adapter = genreAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class AbsHomeViewItem(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val recyclerView: RecyclerView = itemView.findViewById(R.id.recyclerView)
|
||||
val title: AppCompatTextView = itemView.findViewById(R.id.title)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -45,6 +46,7 @@ class SearchAdapter(
|
|||
private var dataSet: List<Any>
|
||||
) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun swapDataSet(dataSet: List<Any>) {
|
||||
this.dataSet = dataSet
|
||||
notifyDataSetChanged()
|
||||
|
@ -148,13 +150,13 @@ class SearchAdapter(
|
|||
imageTextContainer?.isInvisible = true
|
||||
if (itemViewType == SONG) {
|
||||
imageTextContainer?.isGone = true
|
||||
menu?.visibility = View.VISIBLE
|
||||
menu?.isVisible = true
|
||||
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
|
||||
override val song: Song
|
||||
get() = dataSet[layoutPosition] as Song
|
||||
})
|
||||
} else {
|
||||
menu?.visibility = View.GONE
|
||||
menu?.isVisible = false
|
||||
}
|
||||
|
||||
when (itemViewType) {
|
||||
|
@ -162,7 +164,7 @@ class SearchAdapter(
|
|||
ARTIST -> setImageTransitionName(activity.getString(R.string.transition_artist_image))
|
||||
else -> {
|
||||
val container = itemView.findViewById<View>(R.id.imageContainer)
|
||||
container?.visibility = View.GONE
|
||||
container?.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,9 +203,8 @@ class SearchAdapter(
|
|||
)
|
||||
}
|
||||
SONG -> {
|
||||
val playList = mutableListOf<Song>()
|
||||
playList.add(item as Song)
|
||||
MusicPlayerRemote.openQueue(playList, 0, true)
|
||||
MusicPlayerRemote.playNext(item as Song)
|
||||
MusicPlayerRemote.playNextSong()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
||||
|
@ -78,7 +79,7 @@ class SongFileAdapter(
|
|||
if (holder.itemViewType == FILE) {
|
||||
holder.text?.text = getFileText(file)
|
||||
} else {
|
||||
holder.text?.visibility = View.GONE
|
||||
holder.text?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
||||
|
@ -174,7 +175,7 @@ open class AlbumAdapter(
|
|||
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
||||
|
||||
init {
|
||||
menu?.visibility = View.GONE
|
||||
menu?.isVisible = false
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.adapter.artist
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Resources
|
||||
import android.view.LayoutInflater
|
||||
|
@ -21,6 +22,7 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
||||
|
@ -52,13 +54,17 @@ class ArtistAdapter(
|
|||
activity, ICabHolder, R.menu.menu_media_selection
|
||||
), PopupTextProvider {
|
||||
|
||||
var albumArtistsOnly = false
|
||||
|
||||
init {
|
||||
this.setHasStableIds(true)
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun swapDataSet(dataSet: List<Artist>) {
|
||||
this.dataSet = dataSet
|
||||
notifyDataSetChanged()
|
||||
albumArtistsOnly = PreferenceUtil.albumArtistsOnly
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
|
@ -86,7 +92,7 @@ class ArtistAdapter(
|
|||
holder.title?.text = artist.name
|
||||
holder.text?.hide()
|
||||
val transitionName =
|
||||
if (PreferenceUtil.albumArtistsOnly) artist.name else artist.id.toString()
|
||||
if (albumArtistsOnly) artist.name else artist.id.toString()
|
||||
if (holder.imageContainer != null) {
|
||||
ViewCompat.setTransitionName(holder.imageContainer!!, transitionName)
|
||||
} else {
|
||||
|
@ -158,7 +164,7 @@ class ArtistAdapter(
|
|||
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
||||
|
||||
init {
|
||||
menu?.visibility = View.GONE
|
||||
menu?.isVisible = false
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
|
@ -168,7 +174,7 @@ class ArtistAdapter(
|
|||
} else {
|
||||
val artist = dataSet[layoutPosition]
|
||||
image?.let {
|
||||
if (PreferenceUtil.albumArtistsOnly && IAlbumArtistClickListener != null) {
|
||||
if (albumArtistsOnly && IAlbumArtistClickListener != null) {
|
||||
IAlbumArtistClickListener.onAlbumArtist(artist.name, imageContainer ?: it)
|
||||
} else {
|
||||
IArtistClickListener.onArtist(artist.id, imageContainer ?: it)
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.view.MenuItem
|
|||
import androidx.annotation.MenuRes
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.interfaces.ICabCallback
|
||||
|
@ -31,7 +32,10 @@ abstract class AbsMultiSelectAdapter<V : RecyclerView.ViewHolder?, I>(
|
|||
|
||||
override fun onCabFinished(cab: AttachedCab): Boolean {
|
||||
clearChecked()
|
||||
activity.window.statusBarColor = Color.TRANSPARENT
|
||||
activity.window.statusBarColor = when {
|
||||
VersionUtils.hasMarshmallow() -> Color.TRANSPARENT
|
||||
else -> Color.BLACK
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.adapter.song
|
|||
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
|
@ -129,7 +130,7 @@ class OrderablePlaylistSongAdapter(
|
|||
}
|
||||
|
||||
init {
|
||||
dragView?.visibility = View.VISIBLE
|
||||
dragView?.isVisible = true
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.adapter.song
|
|||
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
|
@ -154,7 +155,7 @@ class PlayingQueueAdapter(
|
|||
}
|
||||
|
||||
init {
|
||||
dragView?.visibility = View.VISIBLE
|
||||
dragView?.isVisible = true
|
||||
}
|
||||
|
||||
override fun onSongMenuItemClick(item: MenuItem): Boolean {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package code.name.monkey.retromusic.adapter.song
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.extensions.accentColor
|
||||
|
@ -61,7 +62,7 @@ class ShuffleButtonSongAdapter(
|
|||
super.onBindViewHolder(holder, position - 1)
|
||||
val landscape = RetroUtil.isLandscape()
|
||||
if ((PreferenceUtil.songGridSize > 2 && !landscape) || (PreferenceUtil.songGridSizeLand > 5 && landscape)) {
|
||||
holder.menu?.visibility = View.GONE
|
||||
holder.menu?.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ open class SongAdapter(
|
|||
holder.title?.setTextColor(color.primaryTextColor)
|
||||
holder.text?.setTextColor(color.secondaryTextColor)
|
||||
holder.paletteColorContainer?.setBackgroundColor(color.backgroundColor)
|
||||
holder.menu?.imageTintList= ColorStateList.valueOf(color.primaryTextColor)
|
||||
holder.menu?.imageTintList = ColorStateList.valueOf(color.primaryTextColor)
|
||||
}
|
||||
holder.mask?.backgroundTintList = ColorStateList.valueOf(color.primaryTextColor)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Hemanth Savarla.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
package code.name.monkey.retromusic.appwidgets
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.widget.RemoteViews
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.MainActivity
|
||||
import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.service.MusicService.ACTION_TOGGLE_PAUSE
|
||||
import code.name.monkey.retromusic.service.MusicService.TOGGLE_FAVORITE
|
||||
import code.name.monkey.retromusic.util.ImageUtil
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class AppWidgetCircle : BaseAppWidget() {
|
||||
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
|
||||
|
||||
/**
|
||||
* Initialize given widgets to default state, where we launch Music on default click and hide
|
||||
* actions if service not running.
|
||||
*/
|
||||
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
|
||||
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_circle)
|
||||
|
||||
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art)
|
||||
val secondaryColor = MaterialValueHelper.getSecondaryTextColor(context, true)
|
||||
appWidgetView.setImageViewBitmap(
|
||||
R.id.button_toggle_play_pause, createBitmap(
|
||||
RetroUtil.getTintedVectorDrawable(
|
||||
context,
|
||||
R.drawable.ic_play_arrow,
|
||||
secondaryColor
|
||||
), 1f
|
||||
)
|
||||
)
|
||||
|
||||
linkButtons(context, appWidgetView)
|
||||
pushUpdate(context, appWidgetIds, appWidgetView)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all active widget instances by pushing changes
|
||||
*/
|
||||
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
|
||||
val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_circle)
|
||||
|
||||
val isPlaying = service.isPlaying
|
||||
val song = service.currentSong
|
||||
|
||||
// Set correct drawable for pause state
|
||||
val playPauseRes =
|
||||
if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play_arrow
|
||||
appWidgetView.setImageViewBitmap(
|
||||
R.id.button_toggle_play_pause, createBitmap(
|
||||
RetroUtil.getTintedVectorDrawable(
|
||||
service,
|
||||
playPauseRes,
|
||||
MaterialValueHelper.getSecondaryTextColor(service, true)
|
||||
), 1f
|
||||
)
|
||||
)
|
||||
val isFavorite = runBlocking(Dispatchers.IO) {
|
||||
return@runBlocking MusicUtil.repository.isSongFavorite(song.id)
|
||||
}
|
||||
val favoriteRes =
|
||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||
appWidgetView.setImageViewBitmap(
|
||||
R.id.button_toggle_favorite, createBitmap(
|
||||
RetroUtil.getTintedVectorDrawable(
|
||||
service,
|
||||
favoriteRes,
|
||||
MaterialValueHelper.getSecondaryTextColor(service, true)
|
||||
), 1f
|
||||
)
|
||||
)
|
||||
|
||||
// Link actions buttons to intents
|
||||
linkButtons(service, appWidgetView)
|
||||
|
||||
if (imageSize == 0) {
|
||||
val p = RetroUtil.getScreenSize(service)
|
||||
imageSize = p.x.coerceAtMost(p.y)
|
||||
}
|
||||
|
||||
// Load the album cover async and push the update on completion
|
||||
service.runOnUiThread {
|
||||
if (target != null) {
|
||||
Glide.with(service).clear(target)
|
||||
}
|
||||
target = GlideApp.with(service).asBitmapPalette().songCoverOptions(song)
|
||||
.load(RetroGlideExtension.getSongModel(song))
|
||||
.apply(
|
||||
RequestOptions().transform(RoundedCorners(imageSize / 2))
|
||||
)
|
||||
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
|
||||
override fun onResourceReady(
|
||||
resource: BitmapPaletteWrapper,
|
||||
transition: Transition<in BitmapPaletteWrapper>?
|
||||
) {
|
||||
val palette = resource.palette
|
||||
update(
|
||||
resource.bitmap, palette.getVibrantColor(
|
||||
palette.getMutedColor(
|
||||
MaterialValueHelper.getSecondaryTextColor(
|
||||
service, true
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||
super.onLoadFailed(errorDrawable)
|
||||
update(null, MaterialValueHelper.getSecondaryTextColor(service, true))
|
||||
}
|
||||
|
||||
private fun update(bitmap: Bitmap?, color: Int) {
|
||||
// Set correct drawable for pause state
|
||||
appWidgetView.setImageViewBitmap(
|
||||
R.id.button_toggle_play_pause, ImageUtil.createBitmap(
|
||||
ImageUtil.getTintedVectorDrawable(
|
||||
service, playPauseRes, color
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Set favorite button drawables
|
||||
appWidgetView.setImageViewBitmap(
|
||||
R.id.button_toggle_favorite, ImageUtil.createBitmap(
|
||||
ImageUtil.getTintedVectorDrawable(
|
||||
service, favoriteRes, color
|
||||
)
|
||||
)
|
||||
)
|
||||
appWidgetView.setImageViewBitmap(R.id.image, bitmap)
|
||||
|
||||
pushUpdate(service, appWidgetIds, appWidgetView)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link up various button actions using [PendingIntent].
|
||||
*/
|
||||
private fun linkButtons(context: Context, views: RemoteViews) {
|
||||
val action = Intent(context, MainActivity::class.java)
|
||||
.putExtra(
|
||||
MainActivity.EXPAND_PANEL,
|
||||
PreferenceUtil.isExpandPanel
|
||||
)
|
||||
|
||||
val serviceName = ComponentName(context, MusicService::class.java)
|
||||
|
||||
// Home
|
||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
var pendingIntent =
|
||||
PendingIntent.getActivity(
|
||||
context, 0, action, if (VersionUtils.hasMarshmallow())
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
else 0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.image, pendingIntent)
|
||||
// Favorite track
|
||||
pendingIntent = buildPendingIntent(context, TOGGLE_FAVORITE, serviceName)
|
||||
views.setOnClickPendingIntent(R.id.button_toggle_favorite, pendingIntent)
|
||||
|
||||
// Play and pause
|
||||
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
||||
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val NAME = "app_widget_circle"
|
||||
|
||||
private var mInstance: AppWidgetCircle? = null
|
||||
private var imageSize = 0
|
||||
|
||||
val instance: AppWidgetCircle
|
||||
@Synchronized get() {
|
||||
if (mInstance == null) {
|
||||
mInstance = AppWidgetCircle()
|
||||
}
|
||||
return mInstance!!
|
||||
}
|
||||
}
|
||||
}
|
|
@ -208,7 +208,13 @@ class AppWidgetMD3 : BaseAppWidget() {
|
|||
|
||||
val image = getAlbumArtDrawable(service.resources, bitmap)
|
||||
val roundedBitmap = createRoundedBitmap(
|
||||
image, imageSize, imageSize, cardRadius, cardRadius, cardRadius, cardRadius
|
||||
image,
|
||||
imageSize,
|
||||
imageSize,
|
||||
cardRadius,
|
||||
cardRadius,
|
||||
cardRadius,
|
||||
cardRadius
|
||||
)
|
||||
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ abstract class BaseAppWidget : AppWidgetProvider() {
|
|||
*/
|
||||
fun notifyChange(service: MusicService, what: String) {
|
||||
if (hasInstances(service)) {
|
||||
if (META_CHANGED == what || PLAY_STATE_CHANGED == what) {
|
||||
if (META_CHANGED == what || PLAY_STATE_CHANGED == what || FAVORITE_STATE_CHANGED == what) {
|
||||
performUpdate(service, null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package code.name.monkey.retromusic.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.DialogPlaybackSpeedBinding
|
||||
import code.name.monkey.retromusic.extensions.accent
|
||||
import code.name.monkey.retromusic.extensions.colorButtons
|
||||
import code.name.monkey.retromusic.extensions.materialDialog
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import com.google.android.material.slider.Slider
|
||||
|
||||
class PlaybackSpeedDialog : DialogFragment() {
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val binding = DialogPlaybackSpeedBinding.inflate(layoutInflater)
|
||||
binding.playbackSpeedSlider.accent()
|
||||
binding.playbackPitchSlider.accent()
|
||||
binding.playbackSpeedSlider.addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
|
||||
binding.speedValue.text = "$value"
|
||||
})
|
||||
binding.playbackPitchSlider.addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
|
||||
binding.pitchValue.text = "$value"
|
||||
})
|
||||
binding.playbackSpeedSlider.value = PreferenceUtil.playbackSpeed
|
||||
binding.playbackPitchSlider.value = PreferenceUtil.playbackPitch
|
||||
|
||||
return materialDialog(R.string.playback_settings)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.save) { _, _ ->
|
||||
updatePlaybackAndPitch(
|
||||
binding.playbackSpeedSlider.value,
|
||||
binding.playbackPitchSlider.value
|
||||
)
|
||||
}
|
||||
.setNeutralButton(R.string.reset_action) {_, _ ->
|
||||
updatePlaybackAndPitch(
|
||||
1F,
|
||||
1F
|
||||
)
|
||||
}
|
||||
.setView(binding.root)
|
||||
.create()
|
||||
.colorButtons()
|
||||
}
|
||||
|
||||
private fun updatePlaybackAndPitch(speed: Float, pitch: Float) {
|
||||
PreferenceUtil.playbackSpeed = speed
|
||||
PreferenceUtil.playbackPitch = pitch
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(): PlaybackSpeedDialog {
|
||||
return PlaybackSpeedDialog()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.dialogs
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlarmManager
|
||||
import android.app.Dialog
|
||||
import android.app.PendingIntent
|
||||
|
@ -23,7 +22,6 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.CheckBox
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
|
@ -31,6 +29,7 @@ import android.widget.Toast
|
|||
import androidx.fragment.app.DialogFragment
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.DialogSleepTimerBinding
|
||||
import code.name.monkey.retromusic.extensions.addAccentColor
|
||||
import code.name.monkey.retromusic.extensions.colorButtons
|
||||
import code.name.monkey.retromusic.extensions.materialDialog
|
||||
|
@ -49,31 +48,27 @@ class SleepTimerDialog : DialogFragment() {
|
|||
private lateinit var timerUpdater: TimerUpdater
|
||||
private lateinit var dialog: MaterialDialog
|
||||
private lateinit var shouldFinishLastSong: CheckBox
|
||||
private lateinit var seekBar: SeekBar
|
||||
private lateinit var timerDisplay: TextView
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
timerUpdater = TimerUpdater()
|
||||
val layout =
|
||||
LayoutInflater.from(requireContext()).inflate(R.layout.dialog_sleep_timer, null)
|
||||
shouldFinishLastSong = layout.findViewById(R.id.shouldFinishLastSong)
|
||||
seekBar = layout.findViewById(R.id.seekBar)
|
||||
timerDisplay = layout.findViewById(R.id.timerDisplay)
|
||||
val binding = DialogSleepTimerBinding.inflate(layoutInflater)
|
||||
shouldFinishLastSong = binding.shouldFinishLastSong
|
||||
timerDisplay = binding.timerDisplay
|
||||
|
||||
val finishMusic = PreferenceUtil.isSleepTimerFinishMusic
|
||||
shouldFinishLastSong.apply {
|
||||
addAccentColor()
|
||||
isChecked = finishMusic
|
||||
}
|
||||
seekBar.apply {
|
||||
binding.seekBar.apply {
|
||||
addAccentColor()
|
||||
seekArcProgress = PreferenceUtil.lastSleepTimerValue
|
||||
updateTimeDisplayTime()
|
||||
seekBar.progress = seekArcProgress
|
||||
progress = seekArcProgress
|
||||
}
|
||||
|
||||
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
|
||||
if (i < 1) {
|
||||
seekBar.progress = 1
|
||||
|
@ -91,7 +86,7 @@ class SleepTimerDialog : DialogFragment() {
|
|||
}
|
||||
})
|
||||
return materialDialog(R.string.action_sleep_timer)
|
||||
.setView(layout)
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(R.string.action_set) { _, _ ->
|
||||
PreferenceUtil.isSleepTimerFinishMusic = shouldFinishLastSong.isChecked
|
||||
val minutes = seekArcProgress
|
||||
|
@ -170,7 +165,6 @@ class SleepTimerDialog : DialogFragment() {
|
|||
) {
|
||||
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
seekBar.progress = millisUntilFinished.toInt()
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
|
|
|
@ -4,14 +4,11 @@ import android.app.ActivityManager
|
|||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.*
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.appthemehelper.ATH
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
|
@ -25,6 +22,22 @@ fun AppCompatActivity.toggleScreenOn() {
|
|||
}
|
||||
}
|
||||
|
||||
fun AppCompatActivity.keepScreenOn(keepScreenOn: Boolean) {
|
||||
if (keepScreenOn) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setEdgeToEdgeOrImmersive() {
|
||||
if (PreferenceUtil.isFullScreenMode) {
|
||||
setImmersiveFullscreen()
|
||||
} else {
|
||||
setDrawBehindSystemBars()
|
||||
}
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setImmersiveFullscreen() {
|
||||
if (PreferenceUtil.isFullScreenMode) {
|
||||
WindowInsetsControllerCompat(window, window.decorView).apply {
|
||||
|
@ -36,6 +49,14 @@ fun AppCompatActivity.setImmersiveFullscreen() {
|
|||
window.attributes.layoutInDisplayCutoutMode =
|
||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
}
|
||||
ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { _, insets ->
|
||||
if (insets.displayCutout != null) {
|
||||
insets
|
||||
} else {
|
||||
// Consume insets if display doesn't have a Cutout
|
||||
WindowInsetsCompat.CONSUMED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,19 +78,19 @@ private fun AppCompatActivity.hideStatusBar(fullscreen: Boolean) {
|
|||
}
|
||||
|
||||
fun AppCompatActivity.setDrawBehindSystemBars() {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
if (VersionUtils.hasOreo()) {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
window.navigationBarColor = Color.TRANSPARENT
|
||||
window.statusBarColor = Color.TRANSPARENT
|
||||
if (VersionUtils.hasQ()) {
|
||||
window.isNavigationBarContrastEnforced = false
|
||||
}
|
||||
window.navigationBarColor = Color.TRANSPARENT
|
||||
window.statusBarColor = Color.TRANSPARENT
|
||||
} else {
|
||||
setNavigationBarColorPreOreo(surfaceColor())
|
||||
if (VersionUtils.hasMarshmallow()) {
|
||||
setStatusBarColor(Color.TRANSPARENT)
|
||||
} else {
|
||||
setStatusBarColor(surfaceColor())
|
||||
setStatusBarColor(Color.BLACK)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,24 +117,49 @@ fun AppCompatActivity.setTaskDescriptionColorAuto() {
|
|||
setTaskDescriptionColor(surfaceColor())
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setLightNavigationAuto() {
|
||||
ATH.setLightNavigationBarAuto(this, surfaceColor())
|
||||
@Suppress("Deprecation")
|
||||
fun AppCompatActivity.setLightStatusBar(enabled: Boolean) {
|
||||
if (VersionUtils.hasMarshmallow()) {
|
||||
val decorView = window.decorView
|
||||
val systemUiVisibility = decorView.systemUiVisibility
|
||||
if (enabled) {
|
||||
decorView.systemUiVisibility =
|
||||
systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
} else {
|
||||
decorView.systemUiVisibility =
|
||||
systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setLightStatusBar(enabled: Boolean) {
|
||||
ATH.setLightStatusBar(this, enabled)
|
||||
fun AppCompatActivity.setLightStatusBarAuto() {
|
||||
setLightStatusBar(surfaceColor().isColorLight)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setLightStatusBarAuto(bgColor: Int) {
|
||||
setLightStatusBar(ColorUtil.isColorLight(bgColor))
|
||||
setLightStatusBar(bgColor.isColorLight)
|
||||
}
|
||||
|
||||
@Suppress("Deprecation")
|
||||
fun AppCompatActivity.setLightNavigationBar(enabled: Boolean) {
|
||||
ATH.setLightNavigationBar(this, enabled)
|
||||
if (VersionUtils.hasOreo()) {
|
||||
val decorView = window.decorView
|
||||
var systemUiVisibility = decorView.systemUiVisibility
|
||||
systemUiVisibility = if (enabled) {
|
||||
systemUiVisibility or SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||
} else {
|
||||
systemUiVisibility and SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
|
||||
}
|
||||
decorView.systemUiVisibility = systemUiVisibility
|
||||
}
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setLightNavigationBarAuto() {
|
||||
setLightNavigationBar(surfaceColor().isColorLight)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setLightNavigationBarAuto(bgColor: Int) {
|
||||
setLightNavigationBar(ColorUtil.isColorLight(bgColor))
|
||||
setLightNavigationBar(bgColor.isColorLight)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ import com.google.android.material.button.MaterialButton
|
|||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
|
||||
fun Int.ripAlpha(): Int {
|
||||
|
@ -112,6 +113,22 @@ fun SeekBar.addAccentColor() {
|
|||
thumbTintList = colorState
|
||||
}
|
||||
|
||||
fun Slider.addAccentColor() {
|
||||
if (materialYou) return
|
||||
val accentColor = ThemeStore.accentColor(context)
|
||||
trackActiveTintList = accentColor.colorStateList
|
||||
trackInactiveTintList = ColorUtil.withAlpha(accentColor, 0.5F).colorStateList
|
||||
thumbTintList = accentColor.colorStateList
|
||||
}
|
||||
|
||||
fun Slider.accent() {
|
||||
if (materialYou) return
|
||||
val accentColor = context.accentColor()
|
||||
thumbTintList = accentColor.colorStateList
|
||||
trackActiveTintList = accentColor.colorStateList
|
||||
trackInactiveTintList = ColorUtil.withAlpha(accentColor, 0.1F).colorStateList
|
||||
}
|
||||
|
||||
fun Button.accentTextColor() {
|
||||
if (materialYou) return
|
||||
setTextColor(ThemeStore.accentColor(App.getContext()))
|
||||
|
@ -248,15 +265,10 @@ fun Context.getColorCompat(@ColorRes colorRes: Int): Int {
|
|||
|
||||
@ColorInt
|
||||
fun Context.darkAccentColor(): Int {
|
||||
val colorSurfaceVariant = if (surfaceColor().isColorLight) {
|
||||
surfaceColor()
|
||||
} else {
|
||||
surfaceColor().lighterColor
|
||||
}
|
||||
return ColorUtils.blendARGB(
|
||||
accentColor(),
|
||||
colorSurfaceVariant,
|
||||
if (surfaceColor().isColorLight) 0.96f else 0.975f
|
||||
surfaceColor(),
|
||||
if (surfaceColor().isColorLight) 0.9f else 0.92f
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -269,6 +281,15 @@ fun Context.darkAccentColorVariant(): Int {
|
|||
)
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Context.accentColorVariant(): Int {
|
||||
return if (surfaceColor().isColorLight) {
|
||||
accentColor().darkerColor
|
||||
} else {
|
||||
accentColor().lighterColor
|
||||
}
|
||||
}
|
||||
|
||||
inline val @receiver:ColorInt Int.isColorLight
|
||||
get() = ColorUtil.isColorLight(this)
|
||||
|
||||
|
@ -277,3 +298,6 @@ inline val @receiver:ColorInt Int.lighterColor
|
|||
|
||||
inline val @receiver:ColorInt Int.darkerColor
|
||||
get() = ColorUtil.darkenColor(this)
|
||||
|
||||
inline val Int.colorStateList : ColorStateList
|
||||
get() = ColorStateList.valueOf(this)
|
|
@ -17,6 +17,7 @@ package code.name.monkey.retromusic.extensions
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import code.name.monkey.retromusic.R
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
fun DialogFragment.materialDialog(title: Int): MaterialAlertDialogBuilder {
|
||||
|
|
|
@ -21,9 +21,9 @@ fun Fragment.createNewFile(
|
|||
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
|
||||
{ result: ActivityResult ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
val outputStream: OutputStream? =
|
||||
context?.contentResolver?.openOutputStream(result.data?.data!!)
|
||||
write(outputStream, result.data?.data)
|
||||
context?.contentResolver?.openOutputStream(result.data?.data!!)?.use { os->
|
||||
write(os, result.data?.data)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package code.name.monkey.retromusic.extensions
|
||||
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
|
||||
val Song.uri get() = MusicUtil.getSongFileUri(songId = id)
|
|
@ -20,11 +20,11 @@ import android.content.Context
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.Px
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.animation.doOnStart
|
||||
import androidx.core.view.*
|
||||
|
@ -32,11 +32,8 @@ import code.name.monkey.appthemehelper.ThemeStore
|
|||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.updatePadding
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
import com.google.android.material.shape.ShapeAppearanceModel
|
||||
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
|
||||
|
@ -44,19 +41,17 @@ fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
|
|||
}
|
||||
|
||||
fun View.show() {
|
||||
visibility = View.VISIBLE
|
||||
isVisible = true
|
||||
}
|
||||
|
||||
fun View.hide() {
|
||||
visibility = View.GONE
|
||||
isVisible = false
|
||||
}
|
||||
|
||||
fun View.hidden() {
|
||||
visibility = View.INVISIBLE
|
||||
isInvisible = true
|
||||
}
|
||||
|
||||
fun View.showOrHide(show: Boolean) = if (show) show() else hide()
|
||||
|
||||
fun EditText.appHandleColor(): EditText {
|
||||
if (PreferenceUtil.materialYou) return this
|
||||
TintHelper.colorHandles(this, ThemeStore.accentColor(context))
|
||||
|
@ -126,40 +121,50 @@ fun View.focusAndShowKeyboard() {
|
|||
}
|
||||
}
|
||||
|
||||
fun ShapeableImageView.setCircleShape(boolean: Boolean) {
|
||||
addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
||||
val radius = width / 2f
|
||||
shapeAppearanceModel = ShapeAppearanceModel().withCornerSize(radius)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This will draw our view above the navigation bar instead of behind it by adding margins.
|
||||
*/
|
||||
fun View.drawAboveSystemBars(onlyPortrait: Boolean = true) {
|
||||
if (PreferenceUtil.isFullScreenMode) return
|
||||
if (onlyPortrait && RetroUtil.isLandscape()) return
|
||||
// Create a snapshot of the view's margin state
|
||||
val initialMargin = recordInitialMarginForView(this)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
(this)
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
// Apply the insets as a margin to the view.
|
||||
updateLayoutParams<MarginLayoutParams> {
|
||||
leftMargin = initialMargin.left + insets.left
|
||||
bottomMargin = initialMargin.bottom + insets.bottom
|
||||
rightMargin = initialMargin.right + insets.right
|
||||
applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
margin()
|
||||
}
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will draw our view above the navigation bar instead of behind it by adding padding.
|
||||
*/
|
||||
fun View.drawAboveSystemBarsWithPadding(consume: Boolean = false) {
|
||||
fun View.drawAboveSystemBarsWithPadding() {
|
||||
if (PreferenceUtil.isFullScreenMode) return
|
||||
applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun View.drawNextToNavbar() {
|
||||
if (PreferenceUtil.isFullScreenMode) return
|
||||
applyInsetter {
|
||||
type(statusBars = true, navigationBars = true) {
|
||||
padding(horizontal = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun View.updateMargin(
|
||||
@Px left: Int = marginLeft,
|
||||
@Px top: Int = marginTop,
|
||||
@Px right: Int = marginRight,
|
||||
@Px bottom: Int = marginBottom
|
||||
) {
|
||||
(layoutParams as ViewGroup.MarginLayoutParams).updateMargins(left, top, right, bottom)
|
||||
}
|
||||
|
||||
fun View.applyBottomInsets() {
|
||||
if (PreferenceUtil.isFullScreenMode) return
|
||||
val initialPadding = recordInitialPaddingForView(this)
|
||||
|
||||
|
@ -168,11 +173,9 @@ fun View.drawAboveSystemBarsWithPadding(consume: Boolean = false) {
|
|||
) { v: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.updatePadding(
|
||||
left = initialPadding.left + insets.left,
|
||||
bottom = initialPadding.bottom + insets.bottom,
|
||||
right = initialPadding.right + insets.right
|
||||
bottom = initialPadding.bottom + insets.bottom
|
||||
)
|
||||
if (consume) WindowInsetsCompat.CONSUMED else windowInsets
|
||||
windowInsets
|
||||
}
|
||||
requestApplyInsetsWhenAttached()
|
||||
}
|
||||
|
@ -195,47 +198,6 @@ fun View.requestApplyInsetsWhenAttached() {
|
|||
}
|
||||
}
|
||||
|
||||
fun View.drawNextToNavbar() {
|
||||
val initialPadding = recordInitialPaddingForView(this)
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
(this)
|
||||
) { v: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.updatePadding(
|
||||
left = initialPadding.left + insets.left,
|
||||
right = initialPadding.right + insets.right
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
requestApplyInsetsWhenAttached()
|
||||
}
|
||||
|
||||
fun View.addBottomInsets() {
|
||||
// Create a snapshot of the view's margin state
|
||||
val initialMargin = recordInitialMarginForView(this)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
(this)
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
// Apply the insets as a margin to the view.
|
||||
updateLayoutParams<MarginLayoutParams> {
|
||||
bottomMargin = initialMargin.bottom + insets.bottom
|
||||
}
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
|
||||
data class InitialMargin(
|
||||
val left: Int, val top: Int,
|
||||
val right: Int, val bottom: Int
|
||||
)
|
||||
|
||||
fun recordInitialMarginForView(view: View) = InitialMargin(
|
||||
view.marginLeft, view.marginTop, view.marginRight, view.marginBottom
|
||||
)
|
||||
|
||||
|
||||
data class InitialPadding(
|
||||
val left: Int, val top: Int,
|
||||
val right: Int, val bottom: Int
|
||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.fragments
|
|||
|
||||
import android.animation.ValueAnimator
|
||||
import android.widget.Toast
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.lifecycle.*
|
||||
import code.name.monkey.retromusic.*
|
||||
import code.name.monkey.retromusic.db.*
|
||||
|
@ -39,6 +40,7 @@ class LibraryViewModel(
|
|||
|
||||
private val _paletteColor = MutableLiveData<Int>()
|
||||
private val home = MutableLiveData<List<Home>>()
|
||||
private val suggestions = MutableLiveData<List<Song>>()
|
||||
private val albums = MutableLiveData<List<Album>>()
|
||||
private val songs = MutableLiveData<List<Song>>()
|
||||
private val artists = MutableLiveData<List<Artist>>()
|
||||
|
@ -55,6 +57,7 @@ class LibraryViewModel(
|
|||
|
||||
private fun loadLibraryContent() = viewModelScope.launch(IO) {
|
||||
fetchHomeSections()
|
||||
fetchSuggestions()
|
||||
fetchSongs()
|
||||
fetchAlbums()
|
||||
fetchArtists()
|
||||
|
@ -92,39 +95,34 @@ class LibraryViewModel(
|
|||
return home
|
||||
}
|
||||
|
||||
fun getSuggestions(): LiveData<List<Song>> {
|
||||
return suggestions
|
||||
}
|
||||
|
||||
fun getFabMargin(): LiveData<Int> {
|
||||
return fabMargin
|
||||
}
|
||||
|
||||
private fun fetchSongs() {
|
||||
viewModelScope.launch(IO) {
|
||||
private suspend fun fetchSongs() {
|
||||
songs.postValue(repository.allSongs())
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchAlbums() {
|
||||
viewModelScope.launch(IO) {
|
||||
private suspend fun fetchAlbums() {
|
||||
albums.postValue(repository.fetchAlbums())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun fetchArtists() {
|
||||
private suspend fun fetchArtists() {
|
||||
if (PreferenceUtil.albumArtistsOnly) {
|
||||
viewModelScope.launch(IO) {
|
||||
artists.postValue(repository.albumArtists())
|
||||
}
|
||||
} else {
|
||||
viewModelScope.launch(IO) {
|
||||
artists.postValue(repository.fetchArtists())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchPlaylists() {
|
||||
viewModelScope.launch(IO) {
|
||||
private suspend fun fetchPlaylists() {
|
||||
playlists.postValue(repository.fetchPlaylistWithSongs())
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchLegacyPlaylist() {
|
||||
viewModelScope.launch(IO) {
|
||||
|
@ -132,16 +130,16 @@ class LibraryViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun fetchGenres() {
|
||||
viewModelScope.launch(IO) {
|
||||
private suspend fun fetchGenres() {
|
||||
genres.postValue(repository.fetchGenres())
|
||||
}
|
||||
}
|
||||
|
||||
fun fetchHomeSections() {
|
||||
viewModelScope.launch(IO) {
|
||||
private suspend fun fetchHomeSections() {
|
||||
home.postValue(repository.homeSections())
|
||||
}
|
||||
|
||||
private suspend fun fetchSuggestions() {
|
||||
suggestions.postValue(repository.suggestions())
|
||||
}
|
||||
|
||||
fun search(query: String?, filter: Filter) {
|
||||
|
@ -151,7 +149,7 @@ class LibraryViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun forceReload(reloadType: ReloadType) = viewModelScope.launch {
|
||||
fun forceReload(reloadType: ReloadType) = viewModelScope.launch(IO) {
|
||||
when (reloadType) {
|
||||
Songs -> fetchSongs()
|
||||
Albums -> fetchAlbums()
|
||||
|
@ -159,6 +157,7 @@ class LibraryViewModel(
|
|||
HomeSections -> fetchHomeSections()
|
||||
Playlists -> fetchPlaylists()
|
||||
Genres -> fetchGenres()
|
||||
Suggestions -> fetchSuggestions()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +254,7 @@ class LibraryViewModel(
|
|||
}
|
||||
repository.insertSongs(songEntities)
|
||||
} else {
|
||||
if (playlist != Playlist.empty){
|
||||
if (playlist != Playlist.empty) {
|
||||
val playListId = createPlaylist(PlaylistEntity(playlistName = playlist.name))
|
||||
val songEntities = playlist.getSongs().map {
|
||||
it.toSongEntity(playListId)
|
||||
|
@ -382,15 +381,16 @@ class LibraryViewModel(
|
|||
fun setFabMargin(bottomMargin: Int) {
|
||||
val currentValue = DensityUtil.dip2px(App.getContext(), 16F) +
|
||||
bottomMargin
|
||||
if (currentValue != fabMargin.value) {
|
||||
ValueAnimator.ofInt(fabMargin.value!!, currentValue).apply {
|
||||
addUpdateListener {
|
||||
fabMargin.postValue(
|
||||
it.animatedValue as Int
|
||||
(it.animatedValue as Int)
|
||||
)
|
||||
}
|
||||
start()
|
||||
doOnEnd {
|
||||
fabMargin.postValue(currentValue)
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,4 +402,5 @@ enum class ReloadType {
|
|||
HomeSections,
|
||||
Playlists,
|
||||
Genres,
|
||||
Suggestions
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package code.name.monkey.retromusic.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
/**
|
||||
* @param activity, Activity
|
||||
* @param next, if the button is next, if false then it's considered previous
|
||||
*/
|
||||
class MusicSeekSkipTouchListener(val activity: FragmentActivity, val next: Boolean) :
|
||||
View.OnTouchListener {
|
||||
|
||||
var job: Job? = null
|
||||
var counter = 0
|
||||
var wasSeeking = false
|
||||
|
||||
private val gestureDetector = GestureDetector(activity, object :
|
||||
GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onDown(e: MotionEvent?): Boolean {
|
||||
job = activity.lifecycleScope.launch(Dispatchers.Default) {
|
||||
counter = 0
|
||||
while (isActive) {
|
||||
delay(500)
|
||||
wasSeeking = true
|
||||
var seekingDuration = MusicPlayerRemote.songProgressMillis
|
||||
if (next) {
|
||||
seekingDuration += 5000 * (counter.floorDiv(2) + 1)
|
||||
} else {
|
||||
seekingDuration -= 5000 * (counter.floorDiv(2) + 1)
|
||||
}
|
||||
MusicPlayerRemote.seekTo(seekingDuration)
|
||||
counter += 1
|
||||
}
|
||||
}
|
||||
return super.onDown(e)
|
||||
}
|
||||
})
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
|
||||
val action = event?.actionMasked
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
job?.cancel()
|
||||
if (!wasSeeking) {
|
||||
if (next) {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
} else {
|
||||
MusicPlayerRemote.back()
|
||||
}
|
||||
}
|
||||
wasSeeking = false
|
||||
}
|
||||
return gestureDetector.onTouchEvent(event)
|
||||
}
|
||||
}
|
|
@ -107,7 +107,7 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
|
|||
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
||||
drawingViewId = R.id.fragment_container
|
||||
scrimColor = Color.TRANSPARENT
|
||||
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
|
||||
setAllContainerColors(surfaceColor())
|
||||
setPathMotion(MaterialArcMotion())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
|
|||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
if (!handleBackPress()) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,6 +346,13 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
|
|||
libraryViewModel.forceReload(ReloadType.Albums)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (cab.isActive()) {
|
||||
cab.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleBackPress(): Boolean {
|
||||
cab?.let {
|
||||
if (it.isActive()) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.core.os.bundleOf
|
|||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
@ -75,7 +76,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
|||
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
||||
drawingViewId = R.id.fragment_container
|
||||
scrimColor = Color.TRANSPARENT
|
||||
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
|
||||
setAllContainerColors(surfaceColor())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,22 +193,24 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
|||
if (lastFmArtist != null && lastFmArtist.artist != null && lastFmArtist.artist.bio != null) {
|
||||
val bioContent = lastFmArtist.artist.bio.content
|
||||
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
||||
binding.fragmentArtistContent.biographyText.visibility = View.VISIBLE
|
||||
binding.fragmentArtistContent.biographyTitle.visibility = View.VISIBLE
|
||||
binding.fragmentArtistContent.run {
|
||||
biographyText.isVisible = true
|
||||
biographyTitle.isVisible = true
|
||||
biography = HtmlCompat.fromHtml(bioContent, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
binding.fragmentArtistContent.biographyText.text = biography
|
||||
biographyText.text = biography
|
||||
if (lastFmArtist.artist.stats.listeners.isNotEmpty()) {
|
||||
binding.fragmentArtistContent.listeners.show()
|
||||
binding.fragmentArtistContent.listenersLabel.show()
|
||||
binding.fragmentArtistContent.scrobbles.show()
|
||||
binding.fragmentArtistContent.scrobblesLabel.show()
|
||||
binding.fragmentArtistContent.listeners.text =
|
||||
listeners.show()
|
||||
listenersLabel.show()
|
||||
scrobbles.show()
|
||||
scrobblesLabel.show()
|
||||
listeners.text =
|
||||
RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
|
||||
binding.fragmentArtistContent.scrobbles.text =
|
||||
scrobbles.text =
|
||||
RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the "lang" parameter is set and no biography is given, retry with default language
|
||||
if (biography == null && lang != null) {
|
||||
|
|
|
@ -58,7 +58,7 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
|
|||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
if (!handleBackPress()) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -382,4 +382,11 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
|
|||
super.onResume()
|
||||
libraryViewModel.forceReload(ReloadType.Artists)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (cab.isActive()) {
|
||||
cab.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class BackupViewModel : ViewModel() {
|
|||
val backupsLiveData: LiveData<List<File>> = backupsMutableLiveData
|
||||
|
||||
fun loadBackups(context: Context) {
|
||||
BackupHelper.getBackupRoot(context).listFiles { _, name ->
|
||||
BackupHelper.getBackupRoot().listFiles { _, name ->
|
||||
return@listFiles name.endsWith(BackupHelper.BACKUP_EXTENSION)
|
||||
}?.toList()?.let {
|
||||
backupsMutableLiveData.value = it
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package code.name.monkey.retromusic.fragments.backup
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
|
@ -52,7 +53,7 @@ class RestoreActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun updateTheme() {
|
||||
AppCompatDelegate.setDefaultNightMode(ThemeManager.getNightMode(this))
|
||||
AppCompatDelegate.setDefaultNightMode(ThemeManager.getNightMode())
|
||||
|
||||
// Apply dynamic colors to activity if enabled
|
||||
if (PreferenceUtil.materialYou) {
|
||||
|
@ -65,10 +66,10 @@ class RestoreActivity : AppCompatActivity() {
|
|||
|
||||
private fun getFileName(uri: Uri?): String? {
|
||||
when (uri?.scheme) {
|
||||
"file" -> {
|
||||
ContentResolver.SCHEME_FILE -> {
|
||||
return uri.lastPathSegment
|
||||
}
|
||||
"content" -> {
|
||||
ContentResolver.SCHEME_CONTENT -> {
|
||||
val proj = arrayOf(MediaStore.Files.FileColumns.DISPLAY_NAME)
|
||||
contentResolver.query(
|
||||
uri, proj, null, null, null
|
||||
|
|
|
@ -14,14 +14,27 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.core.view.isVisible
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.fragments.MusicSeekSkipTouchListener
|
||||
import code.name.monkey.retromusic.fragments.other.VolumeFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
||||
|
@ -36,22 +49,87 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
|
|||
|
||||
protected abstract fun hide()
|
||||
|
||||
protected abstract fun updateShuffleState()
|
||||
|
||||
protected abstract fun updateRepeatState()
|
||||
|
||||
protected abstract fun setUpProgressSlider()
|
||||
|
||||
abstract fun setColor(color: MediaNotificationProcessor)
|
||||
|
||||
fun showBounceAnimation(view: View) {
|
||||
view.apply {
|
||||
var lastPlaybackControlsColor: Int = 0
|
||||
|
||||
var lastDisabledPlaybackControlsColor: Int = 0
|
||||
|
||||
var isSeeking = false
|
||||
private set
|
||||
|
||||
open val progressSlider: SeekBar? = null
|
||||
|
||||
abstract val shuffleButton: ImageButton
|
||||
|
||||
abstract val repeatButton: ImageButton
|
||||
|
||||
open val nextButton: ImageButton? = null
|
||||
|
||||
open val previousButton: ImageButton? = null
|
||||
|
||||
open val songTotalTime: TextView? = null
|
||||
|
||||
open val songCurrentProgress: TextView? = null
|
||||
|
||||
private var progressAnimator: ObjectAnimator? = null
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider?.max = total
|
||||
|
||||
if (isSeeking) {
|
||||
progressSlider?.progress = progress
|
||||
} else {
|
||||
progressAnimator = ObjectAnimator.ofInt(progressSlider, "progress", progress).apply {
|
||||
duration = SLIDER_ANIMATION_TIME
|
||||
interpolator = LinearInterpolator()
|
||||
start()
|
||||
}
|
||||
|
||||
}
|
||||
songTotalTime?.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress?.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
private fun setUpProgressSlider() {
|
||||
progressSlider?.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
onUpdateProgressViews(
|
||||
progress,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||
isSeeking = true
|
||||
progressViewUpdateHelper.stop()
|
||||
progressAnimator?.cancel()
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
isSeeking = false
|
||||
MusicPlayerRemote.seekTo(seekBar.progress)
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
fun View.showBounceAnimation() {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (view.width / 2).toFloat()
|
||||
pivotY = (view.height / 2).toFloat()
|
||||
isVisible = true
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
|
@ -67,13 +145,74 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
|
|||
}
|
||||
.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
hideVolumeIfAvailable()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setUpProgressSlider()
|
||||
setUpPrevNext()
|
||||
setUpShuffleButton()
|
||||
setUpRepeatButton()
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun setUpPrevNext() {
|
||||
nextButton?.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true))
|
||||
previousButton?.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false))
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
fun updatePrevNextColor() {
|
||||
nextButton?.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton?.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
fun updateShuffleState() {
|
||||
shuffleButton.setColorFilter(
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> lastPlaybackControlsColor
|
||||
else -> lastDisabledPlaybackControlsColor
|
||||
}, PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
|
||||
fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected var volumeFragment: VolumeFragment? = null
|
||||
|
||||
private fun hideVolumeIfAvailable() {
|
||||
|
@ -82,10 +221,20 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
|
|||
.replace(R.id.volumeFragmentContainer, VolumeFragment()).commit()
|
||||
childFragmentManager.executePendingTransactions()
|
||||
volumeFragment =
|
||||
childFragmentManager.findFragmentById(R.id.volumeFragmentContainer) as VolumeFragment?
|
||||
childFragmentManager.findFragmentById(R.id.volumeFragmentContainer) as? VolumeFragment
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SLIDER_ANIMATION_TIME: Long = 400
|
||||
}
|
||||
|
|
|
@ -32,13 +32,14 @@ import android.view.View
|
|||
import android.widget.RelativeLayout
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.graphics.drawable.DrawableWrapper
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.navOptions
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
|
||||
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
|
||||
import code.name.monkey.retromusic.R
|
||||
|
@ -50,6 +51,7 @@ import code.name.monkey.retromusic.db.toSongEntity
|
|||
import code.name.monkey.retromusic.dialogs.*
|
||||
import code.name.monkey.retromusic.extensions.currentFragment
|
||||
import code.name.monkey.retromusic.extensions.hide
|
||||
import code.name.monkey.retromusic.extensions.keepScreenOn
|
||||
import code.name.monkey.retromusic.extensions.whichFragment
|
||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
||||
import code.name.monkey.retromusic.fragments.ReloadType
|
||||
|
@ -78,9 +80,18 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
): Boolean {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
when (item.itemId) {
|
||||
R.id.action_playback_speed -> {
|
||||
PlaybackSpeedDialog.newInstance().show(childFragmentManager, "PLAYBACK_SETTINGS")
|
||||
return true
|
||||
}
|
||||
R.id.action_toggle_lyrics -> {
|
||||
PreferenceUtil.showLyrics = !item.isChecked
|
||||
item.isChecked = !item.isChecked
|
||||
PreferenceUtil.showLyrics = !PreferenceUtil.showLyrics
|
||||
showLyricsIcon(item)
|
||||
if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) {
|
||||
mainActivity.keepScreenOn(true)
|
||||
} else if (!PreferenceUtil.isScreenOnEnabled && !PreferenceUtil.showLyrics) {
|
||||
mainActivity.keepScreenOn(false)
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.action_go_to_lyrics -> {
|
||||
|
@ -162,7 +173,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
return true
|
||||
}
|
||||
R.id.action_sleep_timer -> {
|
||||
SleepTimerDialog().show(parentFragmentManager, TAG)
|
||||
SleepTimerDialog().show(parentFragmentManager, "SLEEP_TIMER")
|
||||
return true
|
||||
}
|
||||
R.id.action_set_as_ringtone -> {
|
||||
|
@ -193,6 +204,18 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
return false
|
||||
}
|
||||
|
||||
private fun showLyricsIcon(item: MenuItem) {
|
||||
val icon =
|
||||
if (PreferenceUtil.showLyrics) R.drawable.ic_lyrics else R.drawable.ic_lyrics_outline
|
||||
val drawable: Drawable = RetroUtil.getTintedVectorDrawable(
|
||||
requireContext(),
|
||||
icon,
|
||||
toolbarIconColor()
|
||||
)
|
||||
item.isChecked = PreferenceUtil.showLyrics
|
||||
item.icon = drawable
|
||||
}
|
||||
|
||||
abstract fun playerToolbar(): Toolbar?
|
||||
|
||||
abstract fun onShow()
|
||||
|
@ -237,7 +260,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
val isFavorite: Boolean =
|
||||
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
||||
withContext(Main) {
|
||||
val icon = if (animate) {
|
||||
val icon = if (animate && VersionUtils.hasMarshmallow()) {
|
||||
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
||||
} else {
|
||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||
|
@ -269,7 +292,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
if (PreferenceUtil.isFullScreenMode &&
|
||||
view.findViewById<View>(R.id.status_bar) != null
|
||||
) {
|
||||
view.findViewById<View>(R.id.status_bar).visibility = View.GONE
|
||||
view.findViewById<View>(R.id.status_bar).isVisible = false
|
||||
}
|
||||
playerAlbumCoverFragment = whichFragment(R.id.playerAlbumCoverFragment)
|
||||
playerAlbumCoverFragment?.setCallbacks(this)
|
||||
|
@ -287,9 +310,8 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
playerToolbar()?.menu?.removeItem(R.id.action_toggle_lyrics)
|
||||
} else {
|
||||
playerToolbar()?.menu?.findItem(R.id.action_toggle_lyrics)?.apply {
|
||||
fixCheckStateOnIcon()
|
||||
isCheckable = true
|
||||
isChecked = PreferenceUtil.showLyrics
|
||||
showLyricsIcon(this)
|
||||
}
|
||||
}
|
||||
requireView().setOnTouchListener(
|
||||
|
@ -413,14 +435,3 @@ fun goToLyrics(activity: Activity) {
|
|||
)
|
||||
}
|
||||
}
|
||||
/** Fixes checked state being ignored by injecting checked state directly into drawable */
|
||||
@SuppressLint("RestrictedApi")
|
||||
class CheckDrawableWrapper(val menuItem: MenuItem) : DrawableWrapper(menuItem.icon) {
|
||||
// inject checked state into drawable state set
|
||||
override fun setState(stateSet: IntArray) = super.setState(
|
||||
if (menuItem.isChecked) stateSet + android.R.attr.state_checked else stateSet
|
||||
)
|
||||
}
|
||||
|
||||
/** Wrap icon drawable with [CheckDrawableWrapper]. */
|
||||
fun MenuItem.fixCheckStateOnIcon() = apply { icon = CheckDrawableWrapper(this) }
|
||||
|
|
|
@ -32,14 +32,11 @@ import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
|
|||
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
|
||||
import code.name.monkey.retromusic.extensions.accentColor
|
||||
import code.name.monkey.retromusic.extensions.dip
|
||||
import code.name.monkey.retromusic.extensions.drawNextToNavbar
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.IScrollHelper
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ThemedFastScroller.create
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import me.zhanghai.android.fastscroll.FastScroller
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
|
||||
|
@ -60,7 +57,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
|||
view.doOnPreDraw { startPostponedEnterTransition() }
|
||||
enterTransition = MaterialFadeThrough().addTarget(binding.recyclerView)
|
||||
reenterTransition = MaterialFadeThrough().addTarget(binding.recyclerView)
|
||||
mainActivity.setSupportActionBar(binding.toolbar)
|
||||
mainActivity.setSupportActionBar(toolbar)
|
||||
mainActivity.supportActionBar?.title = null
|
||||
initLayoutManager()
|
||||
initAdapter()
|
||||
|
@ -99,25 +96,18 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
|||
open fun onShuffleClicked() {
|
||||
}
|
||||
|
||||
fun toolbar(): Toolbar {
|
||||
return binding.toolbar
|
||||
}
|
||||
val toolbar: Toolbar get() = binding.appBarLayout.toolbar
|
||||
|
||||
private fun setupToolbar() {
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(requireView())
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
toolbar.setNavigationOnClickListener {
|
||||
findNavController().navigate(
|
||||
R.id.searchFragment,
|
||||
R.id.action_search,
|
||||
null,
|
||||
navOptions
|
||||
)
|
||||
}
|
||||
val appName = resources.getString(titleRes)
|
||||
binding.appNameText.text = appName
|
||||
binding.toolbarContainer.drawNextToNavbar()
|
||||
binding.appBarLayout.statusBarForeground =
|
||||
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
||||
binding.appBarLayout.title = appName
|
||||
}
|
||||
|
||||
abstract val titleRes: Int
|
||||
|
@ -155,17 +145,19 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
|||
|
||||
private fun checkIsEmpty() {
|
||||
binding.emptyText.setText(emptyMessage)
|
||||
binding.empty.visibility = if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE
|
||||
binding.empty.isVisible = adapter!!.itemCount == 0
|
||||
}
|
||||
|
||||
private fun checkForPadding() {
|
||||
val itemCount: Int = adapter?.itemCount ?: 0
|
||||
|
||||
if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||
binding.recyclerView.updatePadding(bottom = dip(R.dimen.mini_player_height_expanded))
|
||||
binding.recyclerView.updatePadding(
|
||||
bottom = if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||
dip(R.dimen.mini_player_height_expanded)
|
||||
} else {
|
||||
binding.recyclerView.updatePadding(bottom = dip(R.dimen.bottom_nav_height))
|
||||
dip(R.dimen.bottom_nav_height)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun initLayoutManager() {
|
||||
|
@ -209,7 +201,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
|||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
super.onPrepareOptionsMenu(menu)
|
||||
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), binding.toolbar)
|
||||
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), toolbar)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
|
@ -217,9 +209,9 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
|||
inflater.inflate(R.menu.menu_main, menu)
|
||||
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
|
||||
requireContext(),
|
||||
binding.toolbar,
|
||||
toolbar,
|
||||
menu,
|
||||
ATHToolbarActivity.getToolbarBackgroundColor(binding.toolbar)
|
||||
ATHToolbarActivity.getToolbarBackgroundColor(toolbar)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,10 @@ import android.webkit.MimeTypeMap
|
|||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.loader.app.LoaderManager
|
||||
import androidx.loader.content.Loader
|
||||
import androidx.navigation.Navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
|
||||
|
@ -57,12 +58,10 @@ import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader
|
|||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.providers.BlacklistStore
|
||||
import code.name.monkey.retromusic.util.*
|
||||
import code.name.monkey.retromusic.util.DensityUtil.dip2px
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil.startDirectory
|
||||
import code.name.monkey.retromusic.util.ThemedFastScroller.create
|
||||
import code.name.monkey.retromusic.views.BreadCrumbLayout.Crumb
|
||||
import code.name.monkey.retromusic.views.BreadCrumbLayout.SelectionCallback
|
||||
import code.name.monkey.retromusic.views.ScrollingViewOnApplyWindowInsetsListener
|
||||
import com.afollestad.materialcab.attached.AttachedCab
|
||||
import com.afollestad.materialcab.attached.destroy
|
||||
import com.afollestad.materialcab.attached.isActive
|
||||
|
@ -71,7 +70,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import java.io.*
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
|
@ -94,14 +92,10 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
}
|
||||
}
|
||||
private var storageItems = ArrayList<Storage>()
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentFolderBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
_binding = FragmentFolderBinding.bind(view)
|
||||
|
||||
mainActivity.addMusicServiceEventListener(libraryViewModel)
|
||||
mainActivity.setSupportActionBar(binding.toolbar)
|
||||
mainActivity.supportActionBar?.title = null
|
||||
|
@ -118,7 +112,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
override fun handleOnBackPressed() {
|
||||
if (!handleBackPress()) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -128,10 +122,8 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
}
|
||||
|
||||
private fun setUpTitle() {
|
||||
binding.toolbar.setNavigationOnClickListener { v: View? ->
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).setDuration(300)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).setDuration(300)
|
||||
findNavController(v!!).navigate(R.id.searchFragment, null, navOptions)
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
findNavController().navigate(R.id.action_search, null, navOptions)
|
||||
}
|
||||
binding.appNameText.text = resources.getString(R.string.folders)
|
||||
}
|
||||
|
@ -156,12 +148,8 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
override fun onPause() {
|
||||
super.onPause()
|
||||
saveScrollPosition()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
if (_binding != null) {
|
||||
outState.putParcelable(CRUMBS, binding.breadCrumbs.stateWrapper)
|
||||
if (cab.isActive()) {
|
||||
cab.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +296,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
openQueue(songs, startIndex, true)
|
||||
} else {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
mainActivity.slidingPanel,
|
||||
Html.fromHtml(
|
||||
String.format(
|
||||
getString(R.string.not_listed_in_media_store), file1.name
|
||||
|
@ -381,6 +369,8 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.add(0, R.id.action_go_to_start_directory, 1, R.string.action_go_to_start_directory)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.add(0, R.id.action_settings, 2, R.string.action_settings)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.removeItem(R.id.action_grid_size)
|
||||
menu.removeItem(R.id.action_layout_type)
|
||||
menu.removeItem(R.id.action_sort_order)
|
||||
|
@ -416,6 +406,14 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
}
|
||||
return true
|
||||
}
|
||||
R.id.action_settings -> {
|
||||
findNavController().navigate(
|
||||
R.id.settingsActivity,
|
||||
null,
|
||||
navOptions
|
||||
)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
@ -461,8 +459,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
|||
private fun checkIsEmpty() {
|
||||
if (_binding != null) {
|
||||
binding.emptyEmoji.text = getEmojiByUnicode(0x1F631)
|
||||
binding.empty.visibility =
|
||||
if (adapter == null || adapter!!.itemCount == 0) View.VISIBLE else View.GONE
|
||||
binding.empty.isVisible = adapter?.itemCount == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -100,7 +101,7 @@ class GenreDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_
|
|||
private fun checkIsEmpty() {
|
||||
checkForPadding()
|
||||
binding.emptyEmoji.text = getEmojiByUnicode(0x1F631)
|
||||
binding.empty.visibility = if (songAdapter.itemCount == 0) View.VISIBLE else View.GONE
|
||||
binding.empty.isVisible = songAdapter.itemCount == 0
|
||||
}
|
||||
|
||||
private fun checkForPadding() {
|
||||
|
|
|
@ -48,7 +48,7 @@ GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
|
|||
})
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package code.name.monkey.retromusic.fragments.home
|
||||
|
||||
import code.name.monkey.retromusic.databinding.FragmentHomeBinding
|
||||
|
||||
class HomeBinding(
|
||||
homeBinding: FragmentHomeBinding
|
||||
) {
|
||||
val root = homeBinding.root
|
||||
val container = homeBinding.container
|
||||
val contentContainer = homeBinding.contentContainer
|
||||
val appBarLayout = homeBinding.appBarLayout
|
||||
val toolbar = homeBinding.toolbar
|
||||
val bannerImage = homeBinding.imageLayout.bannerImage
|
||||
val userImage = homeBinding.imageLayout.userImage
|
||||
val lastAdded = homeBinding.homeContent.absPlaylists.lastAdded
|
||||
val topPlayed = homeBinding.homeContent.absPlaylists.topPlayed
|
||||
val actionShuffle = homeBinding.homeContent.absPlaylists.actionShuffle
|
||||
val history = homeBinding.homeContent.absPlaylists.history
|
||||
val recyclerView = homeBinding.homeContent.recyclerView
|
||||
val titleWelcome = homeBinding.imageLayout.titleWelcome
|
||||
val appNameText = homeBinding.appNameText
|
||||
val suggestions = homeBinding.homeContent.suggestions
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package code.name.monkey.retromusic.fragments.home
|
||||
|
||||
import code.name.monkey.retromusic.databinding.FragmentBannerHomeBinding
|
||||
import code.name.monkey.retromusic.databinding.FragmentHomeBinding
|
||||
|
||||
class HomeBindingAdapter(
|
||||
homeBinding: FragmentHomeBinding?,
|
||||
bannerHomeBinding: FragmentBannerHomeBinding?
|
||||
) {
|
||||
val root = homeBinding?.root ?: bannerHomeBinding?.root!!
|
||||
val container = homeBinding?.container ?: bannerHomeBinding?.container!!
|
||||
val contentContainer = homeBinding?.contentContainer ?: bannerHomeBinding?.contentContainer!!
|
||||
val appBarLayout = homeBinding?.appBarLayout ?: bannerHomeBinding?.appBarLayout!!
|
||||
val toolbar = homeBinding?.toolbar
|
||||
?: bannerHomeBinding?.toolbar!!
|
||||
val bannerImage = bannerHomeBinding?.bannerImage
|
||||
val userImage = homeBinding?.userImage
|
||||
?: bannerHomeBinding?.userImage!!
|
||||
val lastAdded = homeBinding?.homeContent?.absPlaylists?.lastAdded
|
||||
?: bannerHomeBinding?.homeContent?.absPlaylists?.lastAdded!!
|
||||
val topPlayed = homeBinding?.homeContent?.absPlaylists?.topPlayed
|
||||
?: bannerHomeBinding?.homeContent?.absPlaylists?.topPlayed!!
|
||||
val actionShuffle = homeBinding?.homeContent?.absPlaylists?.actionShuffle
|
||||
?: bannerHomeBinding?.homeContent?.absPlaylists?.actionShuffle!!
|
||||
val history = homeBinding?.homeContent?.absPlaylists?.history
|
||||
?: bannerHomeBinding?.homeContent?.absPlaylists?.history!!
|
||||
val recyclerView = homeBinding?.homeContent?.recyclerView
|
||||
?: bannerHomeBinding?.homeContent?.recyclerView!!
|
||||
val titleWelcome = homeBinding?.titleWelcome ?: bannerHomeBinding?.titleWelcome!!
|
||||
val appNameText = homeBinding?.appNameText ?: bannerHomeBinding?.appNameText!!
|
||||
}
|
|
@ -25,24 +25,29 @@ import androidx.core.os.bundleOf
|
|||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.view.doOnLayout
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
import code.name.monkey.retromusic.*
|
||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
||||
import code.name.monkey.retromusic.databinding.FragmentBannerHomeBinding
|
||||
import code.name.monkey.retromusic.databinding.FragmentHomeBinding
|
||||
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
|
||||
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
|
||||
import code.name.monkey.retromusic.extensions.accentColor
|
||||
import code.name.monkey.retromusic.extensions.drawNextToNavbar
|
||||
import code.name.monkey.retromusic.extensions.elevatedAccentColor
|
||||
import code.name.monkey.retromusic.fragments.ReloadType
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.IScrollHelper
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
|
@ -50,15 +55,15 @@ import com.google.android.material.transition.MaterialFadeThrough
|
|||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
|
||||
class HomeFragment :
|
||||
AbsMainActivityFragment(if (PreferenceUtil.isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home),
|
||||
IScrollHelper {
|
||||
AbsMainActivityFragment(R.layout.fragment_home), IScrollHelper {
|
||||
|
||||
private var _binding: HomeBindingAdapter? = null
|
||||
private var _binding: HomeBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = getBinding(PreferenceUtil.isHomeBanner, view)
|
||||
val homeBinding = FragmentHomeBinding.bind(view)
|
||||
_binding = HomeBinding(homeBinding)
|
||||
mainActivity.setSupportActionBar(binding.toolbar)
|
||||
mainActivity.supportActionBar?.title = null
|
||||
setupListeners()
|
||||
|
@ -75,6 +80,9 @@ class HomeFragment :
|
|||
libraryViewModel.getHome().observe(viewLifecycleOwner, {
|
||||
homeAdapter.swapData(it)
|
||||
})
|
||||
libraryViewModel.getSuggestions().observe(viewLifecycleOwner, {
|
||||
loadSuggestions(it)
|
||||
})
|
||||
|
||||
loadProfile()
|
||||
setupTitle()
|
||||
|
@ -86,7 +94,7 @@ class HomeFragment :
|
|||
binding.toolbar.drawNextToNavbar()
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
view.doOnLayout {
|
||||
adjustPlaylistButtons()
|
||||
|
@ -96,7 +104,7 @@ class HomeFragment :
|
|||
private fun adjustPlaylistButtons() {
|
||||
val buttons =
|
||||
listOf(binding.history, binding.lastAdded, binding.topPlayed, binding.actionShuffle)
|
||||
buttons.maxOf { it.lineCount }.let { maxLineCount->
|
||||
buttons.maxOf { it.lineCount }.let { maxLineCount ->
|
||||
buttons.forEach { button ->
|
||||
// Set the highest line count to every button for consistency
|
||||
button.setLines(maxLineCount)
|
||||
|
@ -150,24 +158,17 @@ class HomeFragment :
|
|||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBinding(homeBanner: Boolean, view: View): HomeBindingAdapter {
|
||||
return if (homeBanner) {
|
||||
val homeBannerBinding = FragmentBannerHomeBinding.bind(view)
|
||||
HomeBindingAdapter(null, homeBannerBinding)
|
||||
} else {
|
||||
val homeBinding = FragmentHomeBinding.bind(view)
|
||||
HomeBindingAdapter(homeBinding, null)
|
||||
// Reload suggestions
|
||||
binding.suggestions.refreshButton.setOnClickListener {
|
||||
libraryViewModel.forceReload(
|
||||
ReloadType.Suggestions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTitle() {
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(binding.root)
|
||||
reenterTransition =
|
||||
MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
findNavController().navigate(R.id.searchFragment, null, navOptions)
|
||||
findNavController().navigate(R.id.action_search, null, navOptions)
|
||||
}
|
||||
val hexColor = String.format("#%06X", 0xFFFFFF and accentColor())
|
||||
val appName = HtmlCompat.fromHtml(
|
||||
|
@ -234,6 +235,51 @@ class HomeFragment :
|
|||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
|
||||
}
|
||||
|
||||
private fun loadSuggestions(songs: List<Song>) {
|
||||
if (songs.isEmpty()) {
|
||||
binding.suggestions.root.isVisible = false
|
||||
return
|
||||
}
|
||||
val images = listOf(
|
||||
binding.suggestions.image1,
|
||||
binding.suggestions.image2,
|
||||
binding.suggestions.image3,
|
||||
binding.suggestions.image4,
|
||||
binding.suggestions.image5,
|
||||
binding.suggestions.image6,
|
||||
binding.suggestions.image7,
|
||||
binding.suggestions.image8
|
||||
)
|
||||
val color = ThemeStore.accentColor(requireContext())
|
||||
binding.suggestions.message.apply {
|
||||
setTextColor(color)
|
||||
setOnClickListener {
|
||||
it.isClickable = false
|
||||
it.postDelayed({ it.isClickable = true }, 500)
|
||||
MusicPlayerRemote.playNext(songs.subList(0, 8))
|
||||
if (!MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.suggestions.card6.setCardBackgroundColor(ColorUtil.withAlpha(color, 0.12f))
|
||||
images.forEachIndexed { index, imageView ->
|
||||
imageView.setOnClickListener {
|
||||
it.isClickable = false
|
||||
it.postDelayed({ it.isClickable = true }, 500)
|
||||
MusicPlayerRemote.playNext(songs[index])
|
||||
if (!MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
}
|
||||
}
|
||||
GlideApp.with(this)
|
||||
.asBitmap()
|
||||
.songCoverOptions(songs[index])
|
||||
.load(RetroGlideExtension.getSongModel(songs[index]))
|
||||
.into(imageView)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val TAG: String = "BannerHomeFragment"
|
||||
|
@ -270,7 +316,7 @@ class HomeFragment :
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
libraryViewModel.fetchHomeSections()
|
||||
libraryViewModel.forceReload(ReloadType.HomeSections)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
|
|
@ -54,7 +54,7 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
|
|||
mainActivity.supportActionBar?.title = null
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
findNavController().navigate(
|
||||
R.id.searchFragment,
|
||||
R.id.action_search,
|
||||
null,
|
||||
navOptions
|
||||
)
|
||||
|
|
|
@ -12,8 +12,10 @@ import androidx.preference.PreferenceManager
|
|||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.SHOW_LYRICS
|
||||
import code.name.monkey.retromusic.databinding.FragmentCoverLyricsBinding
|
||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.base.goToLyrics
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
|
||||
|
@ -45,6 +47,14 @@ class CoverLyricsFragment : AbsMusicServiceFragment(R.layout.fragment_cover_lyri
|
|||
if (PreferenceUtil.showLyrics) {
|
||||
progressViewUpdateHelper?.start()
|
||||
}
|
||||
// Remove background on Fit theme
|
||||
val nps = PreferenceUtil.nowPlayingScreen
|
||||
if (nps == NowPlayingScreen.Fit || nps == NowPlayingScreen.Full) {
|
||||
binding.root.background = null
|
||||
}
|
||||
binding.playerLyricsLine2.setOnClickListener {
|
||||
goToLyrics(requireActivity())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
|
@ -110,7 +120,7 @@ class CoverLyricsFragment : AbsMusicServiceFragment(R.layout.fragment_cover_lyri
|
|||
if (lyrics !is AbsSynchronizedLyrics) return
|
||||
val synchronizedLyrics = lyrics as AbsSynchronizedLyrics
|
||||
|
||||
lyricsLayout.visibility = View.VISIBLE
|
||||
lyricsLayout.isVisible = true
|
||||
lyricsLayout.alpha = 1f
|
||||
|
||||
val oldLine = lyricsLine2.text.toString()
|
||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.fragments.other
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.addCallback
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||
|
@ -32,17 +33,25 @@ import code.name.monkey.retromusic.adapter.song.SongAdapter
|
|||
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding
|
||||
import code.name.monkey.retromusic.db.toSong
|
||||
import code.name.monkey.retromusic.extensions.dipToPix
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||
import code.name.monkey.retromusic.interfaces.IAlbumClickListener
|
||||
import code.name.monkey.retromusic.interfaces.IArtistClickListener
|
||||
import code.name.monkey.retromusic.interfaces.ICabCallback
|
||||
import code.name.monkey.retromusic.interfaces.ICabHolder
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import com.afollestad.materialcab.attached.AttachedCab
|
||||
import com.afollestad.materialcab.attached.destroy
|
||||
import com.afollestad.materialcab.attached.isActive
|
||||
import com.afollestad.materialcab.createCab
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
|
||||
class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail),
|
||||
IArtistClickListener, IAlbumClickListener {
|
||||
IArtistClickListener, IAlbumClickListener, ICabHolder {
|
||||
private val args by navArgs<DetailListFragmentArgs>()
|
||||
private var _binding: FragmentPlaylistDetailBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
@ -88,6 +97,12 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
|||
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
||||
postponeEnterTransition()
|
||||
view.doOnPreDraw { startPostponedEnterTransition() }
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
if (!handleBackPress()) {
|
||||
remove()
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun lastAddedSongs() {
|
||||
|
@ -95,16 +110,16 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
|||
val songAdapter = ShuffleButtonSongAdapter(
|
||||
requireActivity(),
|
||||
mutableListOf(),
|
||||
R.layout.item_list, null
|
||||
R.layout.item_list, this
|
||||
)
|
||||
binding.recyclerView.apply {
|
||||
adapter = songAdapter
|
||||
layoutManager = linearLayoutManager()
|
||||
scheduleLayoutAnimation()
|
||||
}
|
||||
libraryViewModel.recentSongs().observe(viewLifecycleOwner, { songs ->
|
||||
libraryViewModel.recentSongs().observe(viewLifecycleOwner) { songs ->
|
||||
songAdapter.swapDataSet(songs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun topPlayed() {
|
||||
|
@ -112,15 +127,15 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
|||
val songAdapter = ShuffleButtonSongAdapter(
|
||||
requireActivity(),
|
||||
mutableListOf(),
|
||||
R.layout.item_list, null
|
||||
R.layout.item_list, this
|
||||
)
|
||||
binding.recyclerView.apply {
|
||||
adapter = songAdapter
|
||||
layoutManager = linearLayoutManager()
|
||||
}
|
||||
libraryViewModel.playCountSongs().observe(viewLifecycleOwner, { songs ->
|
||||
libraryViewModel.playCountSongs().observe(viewLifecycleOwner) { songs ->
|
||||
songAdapter.swapDataSet(songs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadHistory() {
|
||||
|
@ -129,15 +144,15 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
|||
val songAdapter = ShuffleButtonSongAdapter(
|
||||
requireActivity(),
|
||||
mutableListOf(),
|
||||
R.layout.item_list, null
|
||||
R.layout.item_list, this
|
||||
)
|
||||
binding.recyclerView.apply {
|
||||
adapter = songAdapter
|
||||
layoutManager = linearLayoutManager()
|
||||
}
|
||||
libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner, {
|
||||
libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner) {
|
||||
songAdapter.swapDataSet(it)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadFavorite() {
|
||||
|
@ -145,50 +160,55 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
|||
val songAdapter = SongAdapter(
|
||||
requireActivity(),
|
||||
mutableListOf(),
|
||||
R.layout.item_list, null
|
||||
R.layout.item_list, this
|
||||
)
|
||||
binding.recyclerView.apply {
|
||||
adapter = songAdapter
|
||||
layoutManager = linearLayoutManager()
|
||||
}
|
||||
libraryViewModel.favorites().observe(viewLifecycleOwner, { songEntities ->
|
||||
libraryViewModel.favorites().observe(viewLifecycleOwner) { songEntities ->
|
||||
val songs = songEntities.map { songEntity -> songEntity.toSong() }
|
||||
songAdapter.swapDataSet(songs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun loadArtists(title: Int, type: Int) {
|
||||
binding.toolbar.setTitle(title)
|
||||
libraryViewModel.artists(type).observe(viewLifecycleOwner, { artists ->
|
||||
val artistAdapter = artistAdapter(listOf())
|
||||
binding.recyclerView.apply {
|
||||
adapter = artistAdapter(artists)
|
||||
adapter = artistAdapter
|
||||
layoutManager = gridLayoutManager()
|
||||
}
|
||||
})
|
||||
libraryViewModel.artists(type).observe(viewLifecycleOwner) { artists ->
|
||||
artistAdapter.swapDataSet(artists)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadAlbums(title: Int, type: Int) {
|
||||
binding.toolbar.setTitle(title)
|
||||
libraryViewModel.albums(type).observe(viewLifecycleOwner, { albums ->
|
||||
val albumAdapter = albumAdapter(listOf())
|
||||
binding.recyclerView.apply {
|
||||
adapter = albumAdapter(albums)
|
||||
adapter = albumAdapter
|
||||
layoutManager = gridLayoutManager()
|
||||
}
|
||||
})
|
||||
libraryViewModel.albums(type).observe(viewLifecycleOwner) { albums ->
|
||||
albumAdapter.swapDataSet(albums)
|
||||
}
|
||||
}
|
||||
|
||||
private fun artistAdapter(artists: List<Artist>): ArtistAdapter = ArtistAdapter(
|
||||
requireActivity(),
|
||||
artists,
|
||||
R.layout.item_grid_circle,
|
||||
null, this@DetailListFragment
|
||||
this, this@DetailListFragment
|
||||
)
|
||||
|
||||
private fun albumAdapter(albums: List<Album>): AlbumAdapter = AlbumAdapter(
|
||||
requireActivity(),
|
||||
albums,
|
||||
R.layout.item_grid,
|
||||
null, this@DetailListFragment
|
||||
this, this@DetailListFragment
|
||||
)
|
||||
|
||||
private fun linearLayoutManager(): LinearLayoutManager =
|
||||
|
@ -228,4 +248,37 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
|||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private var cab: AttachedCab? = null
|
||||
|
||||
private fun handleBackPress(): Boolean {
|
||||
cab?.let {
|
||||
if (it.isActive()) {
|
||||
it.destroy()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab {
|
||||
cab?.let {
|
||||
println("Cab")
|
||||
if (it.isActive()) {
|
||||
it.destroy()
|
||||
}
|
||||
}
|
||||
cab = createCab(R.id.toolbar_container) {
|
||||
menu(menuRes)
|
||||
closeDrawable(R.drawable.ic_close)
|
||||
backgroundColor(literal = RetroColorUtil.shiftBackgroundColor(surfaceColor()))
|
||||
slideDown()
|
||||
onCreate { cab, menu -> callback.onCabCreated(cab, menu) }
|
||||
onSelection {
|
||||
callback.onCabItemClicked(it)
|
||||
}
|
||||
onDestroy { callback.onCabFinished(it) }
|
||||
}
|
||||
return cab as AttachedCab
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,16 @@
|
|||
package code.name.monkey.retromusic.fragments.other
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.text.InputType
|
||||
import android.view.*
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.IntentSenderRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -34,19 +41,16 @@ import code.name.monkey.retromusic.databinding.FragmentLyricsBinding
|
|||
import code.name.monkey.retromusic.databinding.FragmentNormalLyricsBinding
|
||||
import code.name.monkey.retromusic.databinding.FragmentSyncedLyricsBinding
|
||||
import code.name.monkey.retromusic.extensions.accentColor
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.extensions.textColorSecondary
|
||||
import code.name.monkey.retromusic.extensions.uri
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.lyrics.LrcView
|
||||
import code.name.monkey.retromusic.model.AudioTagInfo
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.LyricUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import com.afollestad.materialdialogs.LayoutMode
|
||||
import code.name.monkey.retromusic.util.*
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||
import com.afollestad.materialdialogs.input.input
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
|
@ -55,6 +59,7 @@ import kotlinx.coroutines.*
|
|||
import org.jaudiotagger.audio.AudioFileIO
|
||||
import org.jaudiotagger.tag.FieldKey
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
|
||||
class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||
|
@ -95,6 +100,43 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
return transform
|
||||
}
|
||||
|
||||
private lateinit var normalLyricsLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||
private lateinit var newSyncedLyricsLauncher: ActivityResultLauncher<Intent>
|
||||
private lateinit var editSyncedLyricsLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||
|
||||
private lateinit var cacheFile: File
|
||||
private var syncedLyrics: String = ""
|
||||
private lateinit var syncedFileUri: Uri
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// Normal lyrics launcher
|
||||
normalLyricsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
FileUtils.copyFileToUri(requireContext(), cacheFile, song.uri)
|
||||
}
|
||||
}
|
||||
newSyncedLyricsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
context?.contentResolver?.openOutputStream(result.data?.data!!)?.use {
|
||||
it.write(syncedLyrics.toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
editSyncedLyricsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
requireContext().contentResolver.openOutputStream(syncedFileUri)?.use { os ->
|
||||
(os as FileOutputStream).channel.truncate(0)
|
||||
os.write(syncedLyrics.toByteArray())
|
||||
os.flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -105,15 +147,9 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
ViewCompat.setTransitionName(binding.container, "lyrics")
|
||||
|
||||
setupWakelock()
|
||||
|
||||
binding.tabLyrics.setBackgroundColor(surfaceColor())
|
||||
binding.container.setBackgroundColor(surfaceColor())
|
||||
setupViews()
|
||||
setupToolbar()
|
||||
updateTitleSong()
|
||||
if (VersionUtils.hasR()) {
|
||||
binding.editButton.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
|
@ -144,7 +180,6 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
|
||||
private fun setupToolbar() {
|
||||
mainActivity.setSupportActionBar(binding.toolbar)
|
||||
binding.toolbar.setBackgroundColor(surfaceColor())
|
||||
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
findNavController().navigateUp()
|
||||
|
@ -204,7 +239,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
e.printStackTrace()
|
||||
}
|
||||
|
||||
MaterialDialog(requireContext(), BottomSheet(LayoutMode.WRAP_CONTENT)).show {
|
||||
MaterialDialog(requireContext()).show {
|
||||
title(res = R.string.edit_normal_lyrics)
|
||||
input(
|
||||
hintRes = R.string.paste_lyrics_here,
|
||||
|
@ -213,7 +248,24 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
) { _, input ->
|
||||
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
||||
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
|
||||
syncedLyrics = input.toString()
|
||||
GlobalScope.launch {
|
||||
if (VersionUtils.hasR()) {
|
||||
cacheFile = TagWriter.writeTagsToFilesR(
|
||||
requireContext(), AudioTagInfo(
|
||||
listOf(song.data), fieldKeyValueMap, null
|
||||
)
|
||||
)[0]
|
||||
val pendingIntent =
|
||||
MediaStore.createWriteRequest(
|
||||
requireContext().contentResolver,
|
||||
listOf(song.uri)
|
||||
)
|
||||
|
||||
normalLyricsLauncher.launch(
|
||||
IntentSenderRequest.Builder(pendingIntent).build()
|
||||
)
|
||||
} else {
|
||||
TagWriter.writeTagsToFiles(
|
||||
requireContext(), AudioTagInfo(
|
||||
listOf(song.data), fieldKeyValueMap, null
|
||||
|
@ -221,6 +273,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
positiveButton(res = R.string.save) {
|
||||
(lyricsSectionsAdapter.fragments[1].first as NormalLyrics).loadNormalLyrics()
|
||||
}
|
||||
|
@ -233,15 +286,41 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
private fun editSyncedLyrics() {
|
||||
val content: String = LyricUtil.getStringFromLrc(LyricUtil.getSyncedLyricsFile(song))
|
||||
|
||||
MaterialDialog(requireContext(), BottomSheet(LayoutMode.WRAP_CONTENT)).show {
|
||||
MaterialDialog(requireContext()).show {
|
||||
title(res = R.string.edit_synced_lyrics)
|
||||
input(
|
||||
hintRes = R.string.paste_timeframe_lyrics_here,
|
||||
prefill = content,
|
||||
inputType = InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_CLASS_TEXT
|
||||
) { _, input ->
|
||||
if (VersionUtils.hasR()) {
|
||||
syncedLyrics = input.toString()
|
||||
val lrcFile = LyricUtil.getSyncedLyricsFile(song)
|
||||
if (lrcFile?.exists() == true) {
|
||||
syncedFileUri =
|
||||
UriUtil.getUriFromPath(requireContext(), lrcFile.absolutePath)
|
||||
val pendingIntent =
|
||||
MediaStore.createWriteRequest(
|
||||
requireContext().contentResolver,
|
||||
listOf(syncedFileUri)
|
||||
)
|
||||
editSyncedLyricsLauncher.launch(
|
||||
IntentSenderRequest.Builder(pendingIntent).build()
|
||||
)
|
||||
} else {
|
||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
intent.type = "*/*"
|
||||
intent.putExtra(
|
||||
Intent.EXTRA_TITLE,
|
||||
LyricUtil.getLrcOriginalPath(File(song.data).name)
|
||||
)
|
||||
newSyncedLyricsLauncher.launch(intent)
|
||||
}
|
||||
} else {
|
||||
LyricUtil.writeLrc(song, input.toString())
|
||||
}
|
||||
}
|
||||
positiveButton(res = R.string.save) {
|
||||
(lyricsSectionsAdapter.fragments[0].first as SyncedLyrics).loadLRCLyrics()
|
||||
}
|
||||
|
@ -285,11 +364,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
if (lyrics.isNullOrEmpty()) {
|
||||
binding.noLyricsFound.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.noLyricsFound.visibility = View.GONE
|
||||
}
|
||||
binding.noLyricsFound.isVisible = lyrics.isNullOrEmpty()
|
||||
binding.normalLyrics.text = lyrics
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class PlayingQueueRVFragment : AbsRecyclerViewFragment<PlayingQueueAdapter, Line
|
|||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
toolbar().apply {
|
||||
toolbar.apply {
|
||||
setNavigationOnClickListener {
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.preference.PreferenceManager
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.retromusic.LYRICS_TYPE
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.SHOW_LYRICS
|
||||
import code.name.monkey.retromusic.adapter.album.AlbumCoverPagerAdapter
|
||||
|
@ -43,6 +44,7 @@ import code.name.monkey.retromusic.model.lyrics.Lyrics
|
|||
import code.name.monkey.retromusic.transform.CarousalPagerTransformer
|
||||
import code.name.monkey.retromusic.transform.ParallaxPagerTransformer
|
||||
import code.name.monkey.retromusic.util.LyricUtil
|
||||
import code.name.monkey.retromusic.util.LyricsType
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -145,21 +147,6 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
|||
setOnClickListener {
|
||||
goToLyrics(requireActivity())
|
||||
}
|
||||
setOnFlingXListener { velocityX ->
|
||||
when {
|
||||
velocityX < 0 -> {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
true
|
||||
}
|
||||
velocityX > 0 -> {
|
||||
MusicPlayerRemote.playPreviousSong()
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,6 +188,8 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
|||
showLyrics(false)
|
||||
progressViewUpdateHelper?.stop()
|
||||
}
|
||||
} else if (key == LYRICS_TYPE) {
|
||||
maybeInitLyrics()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,13 +212,22 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
|||
}
|
||||
|
||||
private fun showLyrics(visible: Boolean) {
|
||||
ObjectAnimator.ofFloat(lrcView, View.ALPHA, if (visible) 1F else 0F).apply {
|
||||
binding.coverLyrics.isVisible = false
|
||||
binding.lyricsView.isVisible = false
|
||||
binding.viewPager.isVisible = true
|
||||
val lyrics: View = if (PreferenceUtil.lyricsType == LyricsType.REPLACE_COVER) {
|
||||
ObjectAnimator.ofFloat(viewPager, View.ALPHA, if (visible) 0F else 1F).start()
|
||||
lrcView
|
||||
} else {
|
||||
ObjectAnimator.ofFloat(viewPager, View.ALPHA, 1F).start()
|
||||
binding.coverLyrics
|
||||
}
|
||||
ObjectAnimator.ofFloat(lyrics, View.ALPHA, if (visible) 1F else 0F).apply {
|
||||
doOnEnd {
|
||||
_binding?.lyricsView?.isVisible = visible
|
||||
lyrics.isVisible = visible
|
||||
}
|
||||
start()
|
||||
}
|
||||
ObjectAnimator.ofFloat(viewPager, View.ALPHA, if (visible) 0F else 1F).start()
|
||||
}
|
||||
|
||||
private fun maybeInitLyrics() {
|
||||
|
@ -237,7 +235,9 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
|||
// Don't show lyrics container for below conditions
|
||||
if (lyricViewNpsList.contains(nps) && PreferenceUtil.showLyrics) {
|
||||
showLyrics(true)
|
||||
if (PreferenceUtil.lyricsType == LyricsType.REPLACE_COVER) {
|
||||
progressViewUpdateHelper?.start()
|
||||
}
|
||||
} else {
|
||||
showLyrics(false)
|
||||
progressViewUpdateHelper?.stop()
|
||||
|
@ -283,9 +283,9 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
|||
} else {
|
||||
surfaceColor()
|
||||
}
|
||||
Color -> color.backgroundColor
|
||||
Color ,Classic -> color.backgroundColor
|
||||
Blur -> Color.BLACK
|
||||
else -> color.backgroundColor
|
||||
else -> surfaceColor()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,13 +15,12 @@
|
|||
package code.name.monkey.retromusic.fragments.player.adaptive
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
|
@ -32,10 +31,6 @@ import code.name.monkey.retromusic.databinding.FragmentAdaptivePlayerPlaybackCon
|
|||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -43,38 +38,35 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class AdaptivePlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_adaptive_player_playback_controls) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
private var _binding: FragmentAdaptivePlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentAdaptivePlayerPlaybackControlsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
_binding = FragmentAdaptivePlayerPlaybackControlsBinding.bind(view)
|
||||
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation(binding.playPauseButton)
|
||||
}
|
||||
setUpPlayPauseFab()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
|
@ -86,16 +78,6 @@ class AdaptivePlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
|
@ -163,7 +145,14 @@ class AdaptivePlaybackControlsFragment :
|
|||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
|
@ -174,103 +163,9 @@ class AdaptivePlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
override fun show() {}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
override fun hide() {}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
|
|
@ -16,13 +16,13 @@ package code.name.monkey.retromusic.fragments.player.blur
|
|||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
|
@ -36,10 +36,6 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -48,28 +44,32 @@ class BlurPlaybackControlsFragment :
|
|||
AbsPlayerControlsFragment(R.layout.fragment_blur_player_playback_controls) {
|
||||
private var _binding: FragmentBlurPlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentBlurPlayerPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation()
|
||||
}
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -93,16 +93,6 @@ class BlurPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
|
@ -159,7 +149,14 @@ class BlurPlaybackControlsFragment :
|
|||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
|
@ -170,72 +167,6 @@ class BlurPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -253,55 +184,6 @@ class BlurPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun showBounceAnimation() {
|
||||
binding.playPauseButton.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f).start()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -96,11 +96,13 @@ class CardFragment : AbsPlayerFragment(R.layout.fragment_card_player) {
|
|||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
binding.playerToolbar.inflateMenu(R.menu.menu_player)
|
||||
binding.playerToolbar.setNavigationOnClickListener { requireActivity().onBackPressed() }
|
||||
binding.playerToolbar.setOnMenuItemClickListener(this)
|
||||
binding.playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { requireActivity().onBackPressed() }
|
||||
setOnMenuItemClickListener(this@CardFragment)
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(binding.playerToolbar, Color.WHITE, activity)
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, Color.WHITE, activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.graphics.PorterDuff
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
|
@ -35,10 +36,6 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -46,31 +43,29 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class CardPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_card_player_playback_controls) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
private var _binding: FragmentCardPlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.mediaButton.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.mediaButton.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.mediaButton.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.mediaButton.previousButton
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentCardPlayerPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
|
||||
binding.mediaButton.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation(binding.mediaButton.playPauseButton)
|
||||
}
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -94,16 +89,6 @@ class CardPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
|
@ -167,7 +152,14 @@ class CardPlaybackControlsFragment :
|
|||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.mediaButton.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.mediaButton.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
|
@ -178,118 +170,15 @@ class CardPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.mediaButton.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.mediaButton.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.mediaButton.nextButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
binding.mediaButton.previousButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.mediaButton.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.mediaButton.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.mediaButton.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.mediaButton.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.mediaButton.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.mediaButton.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.mediaButton.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.mediaButton.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.mediaButton.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.mediaButton.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
private fun updateProgressTextColor() {
|
||||
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
binding.songTotalTime.setTextColor(color)
|
||||
binding.songCurrentProgress.setTextColor(color)
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
public override fun show() {}
|
||||
|
||||
public override fun hide() {}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
|
|
@ -111,7 +111,8 @@ class CardBlurFragment : AbsPlayerFragment(R.layout.fragment_card_blur_player),
|
|||
setTitleTextColor(Color.WHITE)
|
||||
setSubtitleTextColor(Color.WHITE)
|
||||
ToolbarContentTintHelper.colorizeToolbar(binding.playerToolbar, Color.WHITE, activity)
|
||||
}.setOnMenuItemClickListener(this)
|
||||
setOnMenuItemClickListener(this@CardBlurFragment)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
|
|
|
@ -16,11 +16,11 @@ package code.name.monkey.retromusic.fragments.player.cardblur
|
|||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
|
@ -32,10 +32,7 @@ import code.name.monkey.retromusic.extensions.hide
|
|||
import code.name.monkey.retromusic.extensions.show
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -43,23 +40,29 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class CardBlurPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_card_blur_player_playback_controls) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
private var _binding: FragmentCardBlurPlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.mediaButton.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.mediaButton.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.mediaButton.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.mediaButton.previousButton
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentCardBlurPlayerPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
binding.progressSlider.applyColor(Color.WHITE)
|
||||
}
|
||||
|
||||
override fun setColor(color: MediaNotificationProcessor) {
|
||||
|
@ -96,16 +99,6 @@ class CardBlurPlaybackControlsFragment :
|
|||
binding.songInfo.setTextColor(color)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
|
@ -139,78 +132,6 @@ class CardBlurPlaybackControlsFragment :
|
|||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.mediaButton.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.mediaButton.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.mediaButton.nextButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
binding.mediaButton.previousButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.mediaButton.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.mediaButton.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.mediaButton.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.mediaButton.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.mediaButton.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.mediaButton.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.mediaButton.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.mediaButton.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.mediaButton.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.mediaButton.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.mediaButton.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -228,33 +149,6 @@ class CardBlurPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.applyColor(Color.WHITE)
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package code.name.monkey.retromusic.fragments.player.circle
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
|
@ -22,9 +23,7 @@ import android.graphics.drawable.ColorDrawable
|
|||
import android.graphics.drawable.Drawable
|
||||
import android.media.AudioManager
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
|
@ -34,6 +33,7 @@ import code.name.monkey.appthemehelper.util.*
|
|||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentCirclePlayerBinding
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.MusicSeekSkipTouchListener
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
|
@ -77,17 +77,10 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
|
|||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentCirclePlayerBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentCirclePlayerBinding.bind(view)
|
||||
|
||||
setupViews()
|
||||
binding.title.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -132,10 +125,11 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
|
|||
)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
binding.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true))
|
||||
binding.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false))
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
|
|
|
@ -39,6 +39,7 @@ import code.name.monkey.retromusic.extensions.getSongInfo
|
|||
import code.name.monkey.retromusic.extensions.hide
|
||||
import code.name.monkey.retromusic.extensions.show
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.fragments.MusicSeekSkipTouchListener
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
|
@ -455,10 +456,21 @@ class ClassicPlayerFragment : AbsPlayerFragment(R.layout.fragment_classic_player
|
|||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.playerControlsContainer.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.playerControlsContainer.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
binding.playerControlsContainer.nextButton.setOnTouchListener(
|
||||
MusicSeekSkipTouchListener(
|
||||
requireActivity(),
|
||||
true
|
||||
)
|
||||
)
|
||||
binding.playerControlsContainer.previousButton.setOnTouchListener(
|
||||
MusicSeekSkipTouchListener(
|
||||
requireActivity(),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
|
|
|
@ -16,7 +16,6 @@ package code.name.monkey.retromusic.fragments.player.color
|
|||
|
||||
import android.animation.ValueAnimator
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.animation.doOnEnd
|
||||
|
@ -61,7 +60,7 @@ class ColorFragment : AbsPlayerFragment(R.layout.fragment_color_player) {
|
|||
_binding?.root?.setBackgroundColor(color.backgroundColor)
|
||||
}
|
||||
animator.start()
|
||||
Handler().post {
|
||||
binding.playerToolbar.post {
|
||||
ToolbarContentTintHelper.colorizeToolbar(
|
||||
binding.playerToolbar,
|
||||
color.secondaryTextColor,
|
||||
|
|
|
@ -17,16 +17,15 @@ package code.name.monkey.retromusic.fragments.player.color
|
|||
import android.animation.Animator
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewAnimationUtils
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
|
@ -39,52 +38,43 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class ColorPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_adaptive_player_playback_controls) {
|
||||
AbsPlayerControlsFragment(R.layout.fragment_color_player_playback_controls) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
private var _binding: FragmentColorPlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentColorPlayerPlaybackControlsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
_binding = FragmentColorPlayerPlaybackControlsBinding.bind(view)
|
||||
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -155,80 +145,23 @@ class ColorPlaybackControlsFragment :
|
|||
private fun setUpPlayPauseFab() {
|
||||
TintHelper.setTintAuto(binding.playPauseButton, Color.WHITE, true)
|
||||
TintHelper.setTintAuto(binding.playPauseButton, Color.BLACK, false)
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
binding.playPauseButton.setImageResource(
|
||||
when {
|
||||
MusicPlayerRemote.isPlaying -> binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
||||
else -> binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow)
|
||||
MusicPlayerRemote.isPlaying -> R.drawable.ic_pause
|
||||
else -> R.drawable.ic_play_arrow
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
|
@ -248,32 +181,6 @@ class ColorPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
fun createRevealAnimator(view: View): Animator {
|
||||
val location = IntArray(2)
|
||||
binding.playPauseButton.getLocationOnScreen(location)
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
package code.name.monkey.retromusic.fragments.player.fit
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
|
@ -33,33 +33,41 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
||||
class FitPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_fit_playback_controls) {
|
||||
|
||||
private var _binding: FragmentFitPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentFitPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
|
@ -70,15 +78,6 @@ class FitPlaybackControlsFragment :
|
|||
binding.text.setOnClickListener {
|
||||
goToArtist(requireActivity())
|
||||
}
|
||||
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
|
@ -93,16 +92,6 @@ class FitPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
|
@ -163,7 +152,14 @@ class FitPlaybackControlsFragment :
|
|||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
|
@ -174,72 +170,6 @@ class FitPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -257,55 +187,6 @@ class FitPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun showBounceAnimation() {
|
||||
binding.playPauseButton.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f).start()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
package code.name.monkey.retromusic.fragments.player.flat
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
|
@ -33,11 +33,8 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -45,22 +42,28 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class FlatPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_flat_player_playback_controls), Callback {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
private var _binding: FragmentFlatPlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton?
|
||||
get() = null
|
||||
|
||||
override val previousButton: ImageButton?
|
||||
get() = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentFlatPlayerPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -71,16 +74,6 @@ class FlatPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -157,10 +150,6 @@ class FlatPlaybackControlsFragment :
|
|||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
||||
|
@ -169,13 +158,6 @@ class FlatPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
binding.title.text = song.title
|
||||
|
@ -196,79 +178,6 @@ class FlatPlaybackControlsFragment :
|
|||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -18,7 +18,6 @@ import android.animation.ObjectAnimator
|
|||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.drawable.AnimatedVectorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
|
@ -26,10 +25,13 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentFullPlayerControlsBinding
|
||||
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||
|
@ -44,9 +46,7 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
|
@ -66,17 +66,30 @@ class FullPlaybackControlsFragment :
|
|||
AbsPlayerControlsFragment(R.layout.fragment_full_player_controls),
|
||||
PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
private val libraryViewModel: LibraryViewModel by sharedViewModel()
|
||||
private var _binding: FragmentFullPlayerControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
@ -94,16 +107,6 @@ class FullPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -190,10 +193,6 @@ class FullPlaybackControlsFragment :
|
|||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
setupFavourite()
|
||||
setupMenu()
|
||||
}
|
||||
|
@ -213,43 +212,6 @@ class FullPlaybackControlsFragment :
|
|||
return (parentFragment as FullPlayerFragment).onMenuItemClick(item!!)
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
@ -258,53 +220,6 @@ class FullPlaybackControlsFragment :
|
|||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupFavourite() {
|
||||
binding.songFavourite.setOnClickListener {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
|
@ -320,7 +235,7 @@ class FullPlaybackControlsFragment :
|
|||
val isFavorite: Boolean =
|
||||
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
||||
withContext(Dispatchers.Main) {
|
||||
val icon = if (animate) {
|
||||
val icon = if (animate && VersionUtils.hasMarshmallow()) {
|
||||
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
||||
} else {
|
||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||
|
|
|
@ -28,16 +28,20 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.*
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.RetroBottomSheetBehavior
|
||||
import code.name.monkey.retromusic.adapter.song.PlayingQueueAdapter
|
||||
import code.name.monkey.retromusic.databinding.FragmentGradientPlayerBinding
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.MusicSeekSkipTouchListener
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
|
@ -63,7 +67,8 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
|
||||
class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_player),
|
||||
MusicProgressViewUpdateHelper.Callback, PopupMenu.OnMenuItemClickListener {
|
||||
MusicProgressViewUpdateHelper.Callback,
|
||||
View.OnLayoutChangeListener, PopupMenu.OnMenuItemClickListener {
|
||||
private var lastColor: Int = 0
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
|
@ -126,9 +131,9 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
|||
}
|
||||
|
||||
private fun setupPanel() {
|
||||
binding.colorBackground.doOnLayout {
|
||||
val panel = getQueuePanel()
|
||||
panel.peekHeight = binding.container.height
|
||||
if (!ViewCompat.isLaidOut(binding.colorBackground) || binding.colorBackground.isLayoutRequested) {
|
||||
binding.colorBackground.addOnLayoutChangeListener(this)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,7 +284,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
|||
val isFavorite: Boolean =
|
||||
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
||||
withContext(Dispatchers.Main) {
|
||||
val icon = if (animate) {
|
||||
val icon = if (animate && VersionUtils.hasMarshmallow()) {
|
||||
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
||||
} else {
|
||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||
|
@ -382,10 +387,11 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
|||
)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.playbackControlsFragment.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.playbackControlsFragment.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
binding.playbackControlsFragment.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true))
|
||||
binding.playbackControlsFragment.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false))
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
|
@ -450,7 +456,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
|||
private fun updateLabel() {
|
||||
(MusicPlayerRemote.playingQueue.size - 1).apply {
|
||||
if (this == (MusicPlayerRemote.position)) {
|
||||
binding.nextSong.text = "Last song"
|
||||
binding.nextSong.text = context?.resources?.getString(R.string.last_song)
|
||||
} else {
|
||||
val title = MusicPlayerRemote.playingQueue[MusicPlayerRemote.position + 1].title
|
||||
binding.nextSong.text = title
|
||||
|
@ -458,6 +464,25 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
|||
}
|
||||
}
|
||||
|
||||
override fun onLayoutChange(
|
||||
v: View?,
|
||||
left: Int,
|
||||
top: Int,
|
||||
right: Int,
|
||||
bottom: Int,
|
||||
oldLeft: Int,
|
||||
oldTop: Int,
|
||||
oldRight: Int,
|
||||
oldBottom: Int
|
||||
) {
|
||||
val panel = getQueuePanel()
|
||||
if (panel.state == STATE_COLLAPSED) {
|
||||
panel.peekHeight = binding.container.height
|
||||
} else if (panel.state == STATE_EXPANDED) {
|
||||
panel.peekHeight = binding.container.height + navBarHeight
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
playingQueueAdapter = PlayingQueueAdapter(
|
||||
requireActivity() as AppCompatActivity,
|
||||
|
|
|
@ -37,7 +37,6 @@ class HomePlayerFragment : AbsPlayerFragment(R.layout.fragment_home_player),
|
|||
private var _binding: FragmentHomePlayerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
package code.name.monkey.retromusic.fragments.player.lockscreen
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
|
@ -32,10 +33,7 @@ import code.name.monkey.retromusic.extensions.ripAlpha
|
|||
import code.name.monkey.retromusic.extensions.textColorSecondary
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -46,23 +44,34 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class LockScreenControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_lock_screen_playback_controls) {
|
||||
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
|
||||
private var _binding: FragmentLockScreenPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentLockScreenPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
}
|
||||
|
||||
|
@ -72,16 +81,6 @@ class LockScreenControlsFragment :
|
|||
binding.text.text = String.format("%s - %s", song.artistName, song.albumName)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper?.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper?.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
|
@ -157,72 +156,6 @@ class LockScreenControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpProgressSlider()
|
||||
setUpShuffleButton()
|
||||
setUpRepeatButton()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -240,32 +173,6 @@ class LockScreenControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -19,7 +19,9 @@ import android.graphics.PorterDuff
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
|
@ -30,10 +32,7 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -44,22 +43,35 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class MaterialControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_material_playback_controls) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
private var _binding: FragmentMaterialPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentMaterialPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -83,16 +95,6 @@ class MaterialControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
|
@ -175,103 +177,9 @@ class MaterialControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
public override fun show() {}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_sharp)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_sharp)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one_sharp)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
public override fun hide() {}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
|
|
@ -29,6 +29,7 @@ import code.name.monkey.retromusic.SNOWFALL
|
|||
import code.name.monkey.retromusic.databinding.FragmentPlayerBinding
|
||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
||||
import code.name.monkey.retromusic.extensions.isColorLight
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
|
@ -167,7 +168,7 @@ class PlayerFragment : AbsPlayerFragment(R.layout.fragment_player),
|
|||
}
|
||||
|
||||
private fun startOrStopSnow(isSnowFalling: Boolean) {
|
||||
if (isSnowFalling) {
|
||||
if (isSnowFalling && !surfaceColor().isColorLight) {
|
||||
binding.snowfallView.isVisible = true
|
||||
binding.snowfallView.restartFalling()
|
||||
} else {
|
||||
|
|
|
@ -14,13 +14,12 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.fragments.player.normal
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
|
@ -33,40 +32,41 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
||||
class PlayerPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_player_playback_controls) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
private var _binding: FragmentPlayerPlaybackControlsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentPlayerPlaybackControlsBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation(binding.playPauseButton)
|
||||
}
|
||||
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
binding.text.isSelected = true
|
||||
binding.title.setOnClickListener {
|
||||
|
@ -126,15 +126,6 @@ class PlayerPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
|
@ -161,7 +152,14 @@ class PlayerPlaybackControlsFragment :
|
|||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
|
@ -172,72 +170,6 @@ class PlayerPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -255,32 +187,6 @@ class PlayerPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -20,7 +20,9 @@ import android.graphics.PorterDuff
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
|
@ -30,10 +32,7 @@ import code.name.monkey.retromusic.databinding.FragmentPeakControlPlayerBinding
|
|||
import code.name.monkey.retromusic.extensions.applyColor
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -44,26 +43,29 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
|
||||
class PeakPlayerControlFragment : AbsPlayerControlsFragment(R.layout.fragment_peak_control_player) {
|
||||
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var _binding: FragmentPeakControlPlayerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onViewCreated(
|
||||
view: View,
|
||||
|
@ -71,14 +73,12 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment(R.layout.fragment_pe
|
|||
) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentPeakControlPlayerBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
}
|
||||
override fun show() {}
|
||||
|
||||
override fun hide() {
|
||||
}
|
||||
override fun hide() {}
|
||||
|
||||
override fun setColor(color: MediaNotificationProcessor) {
|
||||
val controlsColor =
|
||||
|
@ -116,108 +116,12 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment(R.layout.fragment_pe
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener {
|
||||
MusicPlayerRemote.toggleShuffleMode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener {
|
||||
MusicPlayerRemote.cycleRepeatMode()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
TintHelper.setTintAuto(binding.playPauseButton, Color.WHITE, true)
|
||||
TintHelper.setTintAuto(binding.playPauseButton, Color.BLACK, false)
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
super.onPlayStateChanged()
|
||||
updatePlayPauseDrawableState()
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
package code.name.monkey.retromusic.fragments.player.plain
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageButton
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
|
@ -35,10 +35,6 @@ import code.name.monkey.retromusic.extensions.hide
|
|||
import code.name.monkey.retromusic.extensions.show
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -50,12 +46,30 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
|||
class PlainPlaybackControlsFragment :
|
||||
AbsPlayerControlsFragment(R.layout.fragment_plain_controls_fragment) {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
private var _binding: FragmentPlainControlsFragmentBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val progressSlider: SeekBar
|
||||
get() = binding.progressSlider
|
||||
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override val songTotalTime: TextView
|
||||
get() = binding.songTotalTime
|
||||
|
||||
override val songCurrentProgress: TextView
|
||||
get() = binding.songCurrentProgress
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
@ -89,59 +103,23 @@ class PlainPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentPlainControlsFragmentBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation()
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
override fun setColor(color: MediaNotificationProcessor) {
|
||||
val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
|
@ -179,53 +157,6 @@ class PlainPlaybackControlsFragment :
|
|||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
binding.playPauseButton.animate()
|
||||
.scaleX(1f)
|
||||
|
@ -243,29 +174,6 @@ class PlainPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun showBounceAnimation() {
|
||||
binding.playPauseButton.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f).start()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
||||
|
@ -274,32 +182,6 @@ class PlainPlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(
|
||||
MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.fragments.player.simple
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.widget.ImageButton
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
|
@ -32,9 +32,6 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
|||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
@ -49,10 +46,17 @@ class SimplePlaybackControlsFragment :
|
|||
private var _binding: FragmentSimpleControlsFragmentBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override val nextButton: ImageButton
|
||||
get() = binding.nextButton
|
||||
|
||||
override val previousButton: ImageButton
|
||||
get() = binding.previousButton
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
|
@ -73,37 +77,15 @@ class SimplePlaybackControlsFragment :
|
|||
updateSong()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentSimpleControlsFragmentBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
setUpPlayPauseFab()
|
||||
binding.title.isSelected = true
|
||||
binding.text.setOnClickListener {
|
||||
goToArtist(requireActivity())
|
||||
}
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBounceAnimation(binding.playPauseButton)
|
||||
}
|
||||
|
||||
binding.title.setOnClickListener {
|
||||
goToAlbum(requireActivity())
|
||||
}
|
||||
|
@ -112,72 +94,6 @@ class SimplePlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
binding.nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.shuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.repeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
binding.title.text = song.title
|
||||
|
@ -213,9 +129,6 @@ class SimplePlaybackControlsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
binding.songCurrentProgress.text = String.format(
|
||||
"%s / %s",
|
||||
|
@ -263,7 +176,14 @@ class SimplePlaybackControlsFragment :
|
|||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
it.showBounceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
|
|
|
@ -14,15 +14,13 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.fragments.player.tiny
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.ImageButton
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentTinyControlsFragmentBinding
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
|
||||
class TinyPlaybackControlsFragment :
|
||||
|
@ -30,14 +28,15 @@ class TinyPlaybackControlsFragment :
|
|||
private var _binding: FragmentTinyControlsFragmentBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun show() {
|
||||
}
|
||||
override val shuffleButton: ImageButton
|
||||
get() = binding.shuffleButton
|
||||
|
||||
override fun hide() {
|
||||
}
|
||||
override val repeatButton: ImageButton
|
||||
get() = binding.repeatButton
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
}
|
||||
override fun show() {}
|
||||
|
||||
override fun hide() {}
|
||||
|
||||
override fun setColor(color: MediaNotificationProcessor) {
|
||||
lastPlaybackControlsColor = color.secondaryTextColor
|
||||
|
@ -50,66 +49,9 @@ class TinyPlaybackControlsFragment :
|
|||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
}
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentTinyControlsFragmentBinding.bind(view)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
binding.playerShuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
binding.playerRepeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> binding.playerShuffleButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
else -> binding.playerShuffleButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
binding.playerRepeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.playerRepeatButton.setColorFilter(
|
||||
lastDisabledPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
binding.playerRepeatButton.setImageResource(R.drawable.ic_repeat)
|
||||
binding.playerRepeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
binding.playerRepeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||
binding.playerRepeatButton.setColorFilter(
|
||||
lastPlaybackControlsColor,
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
|
|
|
@ -59,11 +59,9 @@ class TinyPlayerFragment : AbsPlayerFragment(R.layout.fragment_tiny_player),
|
|||
return binding.playerToolbar
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
}
|
||||
override fun onShow() {}
|
||||
|
||||
override fun onHide() {
|
||||
}
|
||||
override fun onHide() {}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
|
|
|
@ -20,6 +20,7 @@ import code.name.monkey.retromusic.db.PlaylistWithSongs
|
|||
import code.name.monkey.retromusic.db.toSongs
|
||||
import code.name.monkey.retromusic.extensions.dip
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.extensions.updateMargin
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
||||
|
@ -149,8 +150,8 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
}
|
||||
|
||||
private fun showEmptyView() {
|
||||
binding.empty.visibility = View.VISIBLE
|
||||
binding.emptyText.visibility = View.VISIBLE
|
||||
binding.empty.isVisible = true
|
||||
binding.emptyText.isVisible = true
|
||||
}
|
||||
|
||||
fun songs(songs: List<Song>) {
|
||||
|
|
|
@ -48,7 +48,7 @@ class PlaylistsFragment :
|
|||
})
|
||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
|||
}
|
||||
|
||||
private fun updateCurrentSong() {
|
||||
binding.toolbar.subtitle = getUpNextAndQueueTime()
|
||||
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
|
@ -140,7 +140,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
|||
private fun updateQueuePosition() {
|
||||
playingQueueAdapter?.setCurrent(MusicPlayerRemote.position)
|
||||
resetToCurrentPosition()
|
||||
binding.toolbar.subtitle = getUpNextAndQueueTime()
|
||||
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||
}
|
||||
|
||||
private fun updateQueue() {
|
||||
|
@ -179,7 +179,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
|||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
binding.toolbar.subtitle = getUpNextAndQueueTime()
|
||||
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||
binding.clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())
|
||||
ColorStateList.valueOf(
|
||||
MaterialValueHelper.getPrimaryTextColor(
|
||||
|
@ -190,10 +190,13 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
|||
binding.clearQueue.setTextColor(this)
|
||||
binding.clearQueue.iconTint = this
|
||||
}
|
||||
binding.toolbar.apply {
|
||||
binding.appBarLayout.pinWhenScrolled()
|
||||
binding.appBarLayout.toolbar.apply {
|
||||
setNavigationOnClickListener {
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
setTitle(R.string.now_playing_queue)
|
||||
setTitleTextAppearance(context, R.style.ToolbarTextAppearanceNormal)
|
||||
setNavigationIcon(R.drawable.ic_keyboard_backspace_black)
|
||||
ToolbarContentTintHelper.colorBackButton(this)
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ import com.google.android.material.chip.Chip
|
|||
import com.google.android.material.chip.ChipGroup
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
@ -63,8 +63,8 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(view)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
enterTransition = MaterialFadeThrough().addTarget(view)
|
||||
reenterTransition = MaterialFadeThrough().addTarget(view)
|
||||
_binding = FragmentSearchBinding.bind(view)
|
||||
mainActivity.setSupportActionBar(binding.toolbar)
|
||||
libraryViewModel.clearSearchResult()
|
||||
|
@ -147,7 +147,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
|||
super.onChanged()
|
||||
binding.empty.isVisible = searchAdapter.itemCount < 1
|
||||
val height = dipToPix(52f)
|
||||
binding.recyclerView.setPadding(0, 0, 0, height.toInt())
|
||||
binding.recyclerView.updatePadding(bottom = height.toInt())
|
||||
}
|
||||
})
|
||||
binding.recyclerView.apply {
|
||||
|
@ -226,11 +226,6 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
|||
hideKeyboard(view)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mainActivity.setBottomNavVisibility(false)
|
||||
}
|
||||
|
||||
private fun hideKeyboard(view: View?) {
|
||||
if (view != null) {
|
||||
val imm: InputMethodManager =
|
||||
|
|
|
@ -20,18 +20,14 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat
|
||||
import code.name.monkey.retromusic.activities.OnThemeChangedListener
|
||||
import code.name.monkey.retromusic.extensions.rootView
|
||||
import code.name.monkey.retromusic.extensions.safeGetBottomInsets
|
||||
import code.name.monkey.retromusic.preferences.*
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
|
@ -74,19 +70,10 @@ abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() {
|
|||
listView.overScrollMode = View.OVER_SCROLL_NEVER
|
||||
}
|
||||
|
||||
// CollapsingToolbarLayout consumes insets and insets are not passed to child views
|
||||
// So we get insets from decor view
|
||||
// https://github.com/material-components/material-components-android/issues/1310
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
requireActivity().rootView
|
||||
) { _, windowInsets ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
listView.updatePadding(
|
||||
left = insets.left,
|
||||
bottom = insets.bottom,
|
||||
right = insets.right,
|
||||
)
|
||||
windowInsets
|
||||
listView.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
invalidateSettings()
|
||||
}
|
||||
|
|
|
@ -19,17 +19,14 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentMainSettingsBinding
|
||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBarsWithPadding
|
||||
import code.name.monkey.retromusic.extensions.hide
|
||||
import code.name.monkey.retromusic.extensions.rootView
|
||||
import code.name.monkey.retromusic.extensions.show
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
|
||||
|
@ -40,17 +37,20 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
|
|||
|
||||
|
||||
override fun onClick(view: View) {
|
||||
findNavController().navigate(
|
||||
when (view.id) {
|
||||
R.id.generalSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_themeSettingsFragment)
|
||||
R.id.audioSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_audioSettings)
|
||||
R.id.personalizeSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_personalizeSettingsFragment)
|
||||
R.id.imageSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_imageSettingFragment)
|
||||
R.id.notificationSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_notificationSettingsFragment)
|
||||
R.id.otherSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_otherSettingsFragment)
|
||||
R.id.aboutSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_aboutActivity)
|
||||
R.id.nowPlayingSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_nowPlayingSettingsFragment)
|
||||
R.id.backup_restore_settings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_backupFragment)
|
||||
R.id.generalSettings -> R.id.action_mainSettingsFragment_to_themeSettingsFragment
|
||||
R.id.audioSettings -> R.id.action_mainSettingsFragment_to_audioSettings
|
||||
R.id.personalizeSettings -> R.id.action_mainSettingsFragment_to_personalizeSettingsFragment
|
||||
R.id.imageSettings -> R.id.action_mainSettingsFragment_to_imageSettingFragment
|
||||
R.id.notificationSettings -> R.id.action_mainSettingsFragment_to_notificationSettingsFragment
|
||||
R.id.otherSettings -> R.id.action_mainSettingsFragment_to_otherSettingsFragment
|
||||
R.id.aboutSettings -> R.id.action_mainSettingsFragment_to_aboutActivity
|
||||
R.id.nowPlayingSettings -> R.id.action_mainSettingsFragment_to_nowPlayingSettingsFragment
|
||||
R.id.backup_restore_settings -> R.id.action_mainSettingsFragment_to_backupFragment
|
||||
else -> R.id.action_mainSettingsFragment_to_themeSettingsFragment
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -89,17 +89,7 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
|
|||
binding.diamondIcon.imageTintList = ColorStateList.valueOf(it)
|
||||
}
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
requireActivity().rootView
|
||||
) { _, windowInsets ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
_binding?.container?.updatePadding(
|
||||
left = insets.left,
|
||||
bottom = insets.bottom,
|
||||
right = insets.right,
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
binding.container.drawAboveSystemBarsWithPadding()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
|
@ -37,6 +38,7 @@ import com.google.android.material.color.DynamicColors
|
|||
*/
|
||||
|
||||
class ThemeSettingsFragment : AbsSettingsFragment() {
|
||||
@SuppressLint("CheckResult")
|
||||
override fun invalidateSettings() {
|
||||
val generalTheme: Preference? = findPreference(GENERAL_THEME)
|
||||
generalTheme?.let {
|
||||
|
@ -121,6 +123,16 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
|
|||
restartActivity()
|
||||
true
|
||||
}
|
||||
val wallpaperAccent: ATESwitchPreference? = findPreference(WALLPAPER_ACCENT)
|
||||
wallpaperAccent?.setOnPreferenceChangeListener { _, _ ->
|
||||
restartActivity()
|
||||
true
|
||||
}
|
||||
val customFont: ATESwitchPreference? = findPreference(CUSTOM_FONT)
|
||||
customFont?.setOnPreferenceChangeListener { _, _ ->
|
||||
restartActivity()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
|
|
|
@ -51,12 +51,11 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
|
|||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||
if (!handleBackPress()) {
|
||||
remove()
|
||||
mainActivity.finish()
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override val titleRes: Int
|
||||
get() = R.string.songs
|
||||
|
||||
|
@ -346,6 +345,13 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
|
|||
libraryViewModel.forceReload(ReloadType.Songs)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (cab.isActive()) {
|
||||
cab.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
var TAG: String = SongsFragment::class.java.simpleName
|
||||
|
|
|
@ -28,7 +28,7 @@ object BackupHelper : KoinComponent {
|
|||
|
||||
suspend fun createBackup(context: Context, name: String) {
|
||||
val backupFile =
|
||||
File(getBackupRoot(context), name + APPEND_EXTENSION)
|
||||
File(getBackupRoot(), name + APPEND_EXTENSION)
|
||||
if (backupFile.parentFile?.exists() != true) {
|
||||
backupFile.parentFile?.mkdirs()
|
||||
}
|
||||
|
@ -257,9 +257,9 @@ object BackupHelper : KoinComponent {
|
|||
}
|
||||
}
|
||||
|
||||
fun getBackupRoot(context: Context): File {
|
||||
fun getBackupRoot(): File {
|
||||
return File(
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
|
||||
"RetroMusic/Backups"
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,12 +15,10 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.IBinder
|
||||
import android.provider.DocumentsContract
|
||||
|
@ -440,12 +438,14 @@ object MusicPlayerRemote : KoinComponent {
|
|||
} else if (uri.authority == "media") {
|
||||
songId = uri.lastPathSegment
|
||||
}
|
||||
if (songId != null) {
|
||||
songs = songRepository.songs(songId)
|
||||
songs = if (songId != null) {
|
||||
songRepository.songs(songId)
|
||||
} else {
|
||||
songRepository.songsIgnoreBlacklist(uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (songs == null) {
|
||||
if (songs == null || songs.isEmpty()) {
|
||||
var songFile: File? = null
|
||||
if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") {
|
||||
songFile = File(
|
||||
|
@ -462,7 +462,7 @@ object MusicPlayerRemote : KoinComponent {
|
|||
songFile = File(uri.path!!)
|
||||
}
|
||||
if (songFile != null) {
|
||||
songs = songRepository.songsByFilePath(songFile.absolutePath)
|
||||
songs = songRepository.songsByFilePath(songFile.absolutePath, true)
|
||||
}
|
||||
}
|
||||
if (songs != null && songs.isNotEmpty()) {
|
||||
|
@ -474,7 +474,6 @@ object MusicPlayerRemote : KoinComponent {
|
|||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private fun getSongIdFromMediaProvider(uri: Uri): String {
|
||||
return DocumentsContract.getDocumentId(uri).split(":".toRegex())
|
||||
.dropLastWhile { it.isEmpty() }.toTypedArray()[1]
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.app.WallpaperManager
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
|
||||
class WallpaperAccentManager(val context: Context) {
|
||||
|
||||
private val onColorsChangedListener by lazy {
|
||||
WallpaperManager.OnColorsChangedListener { _, _ ->
|
||||
updateColors()
|
||||
}
|
||||
}
|
||||
|
||||
fun init() {
|
||||
if (VersionUtils.hasOreoMR1()) {
|
||||
with(WallpaperManager.getInstance(context)) {
|
||||
updateColors()
|
||||
if (PreferenceUtil.wallpaperAccent) {
|
||||
addOnColorsChangedListener(
|
||||
onColorsChangedListener,
|
||||
Handler(Looper.getMainLooper())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun release() {
|
||||
if (VersionUtils.hasOreoMR1()) {
|
||||
WallpaperManager.getInstance(context)
|
||||
.removeOnColorsChangedListener(onColorsChangedListener)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateColors() {
|
||||
if (VersionUtils.hasOreoMR1()) {
|
||||
val colors = WallpaperManager.getInstance(context)
|
||||
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
|
||||
if (colors != null) {
|
||||
val primaryColor = colors.primaryColor.toArgb()
|
||||
if (primaryColor != ThemeStore.wallpaperColor(context)) {
|
||||
ThemeStore.editTheme(context).wallpaperColor(primaryColor).commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -67,7 +67,6 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
private var mDefaultLabel: String? = null
|
||||
private var mLrcPadding = 0f
|
||||
private var mOnPlayClickListener: OnPlayClickListener? = null
|
||||
private var mOnFlingXListener: OnFlingXListener? = null
|
||||
private var mAnimator: ValueAnimator? = null
|
||||
private var mGestureDetector: GestureDetector? = null
|
||||
private var mScroller: Scroller? = null
|
||||
|
@ -132,9 +131,6 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean {
|
||||
if (mOnFlingXListener != null && abs(velocityX) > abs(velocityY)) {
|
||||
return mOnFlingXListener!!.onFlingX(velocityX)
|
||||
}
|
||||
if (hasLrc()) {
|
||||
mScroller!!.fling(
|
||||
0,
|
||||
|
@ -167,7 +163,7 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
isShowTimeline = false
|
||||
removeCallbacks(hideTimelineRunnable)
|
||||
mCurrentLine = centerLine
|
||||
invalidate()
|
||||
animateCurrentTextSize()
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
|
@ -320,10 +316,6 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
mOnPlayClickListener = onPlayClickListener
|
||||
}
|
||||
|
||||
fun setOnFlingXListener(onFlingXListener: OnFlingXListener) {
|
||||
mOnFlingXListener = onFlingXListener
|
||||
}
|
||||
|
||||
/** 设置歌词为空时屏幕中央显示的文字,如“暂无歌词” */
|
||||
fun setLabel(label: String?) {
|
||||
runOnUi {
|
||||
|
@ -458,6 +450,7 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
mCurrentLine = line
|
||||
if (!isShowTimeline) {
|
||||
smoothScrollTo(line)
|
||||
animateCurrentTextSize()
|
||||
} else {
|
||||
invalidate()
|
||||
}
|
||||
|
@ -536,6 +529,18 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
canvas.restore()
|
||||
}
|
||||
|
||||
fun animateCurrentTextSize() {
|
||||
val currentTextSize = mCurrentTextSize
|
||||
ValueAnimator.ofFloat(mNormalTextSize, currentTextSize).apply {
|
||||
addUpdateListener {
|
||||
mCurrentTextSize = it.animatedValue as Float
|
||||
invalidate()
|
||||
}
|
||||
duration = 300L
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
if (event.action == MotionEvent.ACTION_UP
|
||||
|
@ -613,7 +618,7 @@ class CoverLrcView @JvmOverloads constructor(
|
|||
private fun adjustCenter() {
|
||||
smoothScrollTo(centerLine, ADJUST_DURATION)
|
||||
}
|
||||
/** 滚动到某一行 */
|
||||
|
||||
/** 滚动到某一行 */
|
||||
private fun smoothScrollTo(line: Int, duration: Long = mAnimationDuration) {
|
||||
val offset = getOffset(line)
|
||||
|
|
|
@ -37,6 +37,7 @@ data class CategoryInfo(
|
|||
Artists(R.id.action_artist, R.string.artists, R.drawable.asld_artist),
|
||||
Playlists(R.id.action_playlist, R.string.playlists, R.drawable.asld_playlist),
|
||||
Genres(R.id.action_genre, R.string.genres, R.drawable.asld_guitar),
|
||||
Folder(R.id.action_folder, R.string.folders, R.drawable.asld_folder);
|
||||
Folder(R.id.action_folder, R.string.folders, R.drawable.asld_folder),
|
||||
Search(R.id.action_search, R.string.action_search, R.drawable.ic_search);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
package code.name.monkey.retromusic.preferences
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
|
@ -22,8 +21,6 @@ import android.util.AttributeSet
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
||||
|
@ -33,6 +30,8 @@ import androidx.viewpager.widget.ViewPager
|
|||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.PreferenceDialogNowPlayingScreenBinding
|
||||
import code.name.monkey.retromusic.databinding.PreferenceNowPlayingScreenItemBinding
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
|
||||
import code.name.monkey.retromusic.fragments.AlbumCoverStyle.*
|
||||
|
@ -69,14 +68,13 @@ class AlbumCoverStylePreferenceDialog : DialogFragment(),
|
|||
private var viewPagerPosition: Int = 0
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
@SuppressLint("InflateParams") val view =
|
||||
layoutInflater
|
||||
.inflate(R.layout.preference_dialog_now_playing_screen, null)
|
||||
val viewPager = view.findViewById<ViewPager>(R.id.now_playing_screen_view_pager)
|
||||
viewPager.adapter = AlbumCoverStyleAdapter(requireContext())
|
||||
viewPager.addOnPageChangeListener(this)
|
||||
viewPager.pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt()
|
||||
viewPager.currentItem = PreferenceUtil.albumCoverStyle.ordinal
|
||||
val binding = PreferenceDialogNowPlayingScreenBinding.inflate(layoutInflater)
|
||||
binding.nowPlayingScreenViewPager.apply {
|
||||
adapter = AlbumCoverStyleAdapter(requireContext())
|
||||
addOnPageChangeListener(this@AlbumCoverStylePreferenceDialog)
|
||||
pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt()
|
||||
currentItem = PreferenceUtil.albumCoverStyle.ordinal
|
||||
}
|
||||
|
||||
return materialDialog(R.string.pref_title_album_cover_style)
|
||||
.setPositiveButton(R.string.set) { _, _ ->
|
||||
|
@ -89,7 +87,7 @@ class AlbumCoverStylePreferenceDialog : DialogFragment(),
|
|||
PreferenceUtil.albumCoverStyle = coverStyle
|
||||
}
|
||||
}
|
||||
.setView(view)
|
||||
.setView(binding.root)
|
||||
.create()
|
||||
.colorButtons()
|
||||
}
|
||||
|
@ -111,25 +109,17 @@ class AlbumCoverStylePreferenceDialog : DialogFragment(),
|
|||
val albumCoverStyle = values()[position]
|
||||
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val layout = inflater.inflate(
|
||||
R.layout.preference_now_playing_screen_item,
|
||||
collection,
|
||||
false
|
||||
) as ViewGroup
|
||||
collection.addView(layout)
|
||||
val binding = PreferenceNowPlayingScreenItemBinding.inflate(inflater, collection, true)
|
||||
|
||||
val image = layout.findViewById<ImageView>(R.id.image)
|
||||
val title = layout.findViewById<TextView>(R.id.title)
|
||||
val proText = layout.findViewById<TextView>(R.id.proText)
|
||||
Glide.with(context).load(albumCoverStyle.drawableResId).into(image)
|
||||
title.setText(albumCoverStyle.titleRes)
|
||||
Glide.with(context).load(albumCoverStyle.drawableResId).into(binding.image)
|
||||
binding.title.setText(albumCoverStyle.titleRes)
|
||||
if (isAlbumCoverStyle(albumCoverStyle)) {
|
||||
proText.show()
|
||||
proText.setText(R.string.pro)
|
||||
binding.proText.show()
|
||||
binding.proText.setText(R.string.pro)
|
||||
} else {
|
||||
proText.hide()
|
||||
binding.proText.hide()
|
||||
}
|
||||
return layout
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun destroyItem(
|
||||
|
|
|
@ -1,31 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.preferences
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.util.AttributeSet
|
||||
import android.widget.TextView
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.PreferenceDialogAudioFadeBinding
|
||||
import code.name.monkey.retromusic.extensions.addAccentColor
|
||||
import code.name.monkey.retromusic.extensions.colorButtons
|
||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
||||
import code.name.monkey.retromusic.extensions.materialDialog
|
||||
|
@ -50,29 +36,24 @@ class DurationPreference @JvmOverloads constructor(
|
|||
class DurationPreferenceDialog : DialogFragment() {
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val view = layoutInflater
|
||||
.inflate(R.layout.preference_dialog_audio_fade, null)
|
||||
val binding = PreferenceDialogAudioFadeBinding.inflate(layoutInflater)
|
||||
|
||||
|
||||
val slider = view.findViewById<Slider>(R.id.slider)
|
||||
val duration = view.findViewById<TextView>(R.id.duration)
|
||||
ColorStateList.valueOf(ThemeStore.accentColor(requireContext())).let {
|
||||
slider.trackTintList = it
|
||||
slider.thumbTintList = it
|
||||
}
|
||||
slider.value = PreferenceUtil.audioFadeDuration.toFloat()
|
||||
updateText(slider.value.toInt(), duration)
|
||||
slider.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
|
||||
binding.slider.apply {
|
||||
addAccentColor()
|
||||
value = PreferenceUtil.audioFadeDuration.toFloat()
|
||||
updateText(value.toInt(), binding.duration)
|
||||
addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
|
||||
if (fromUser) {
|
||||
updateText(value.toInt(), duration)
|
||||
updateText(value.toInt(), binding.duration)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return materialDialog(R.string.audio_fade_duration)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.save) { _, _ -> updateDuration(slider.value.toInt()) }
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.save) { _, _ -> updateDuration(binding.slider.value.toInt()) }
|
||||
.setView(binding.root)
|
||||
.create()
|
||||
.colorButtons()
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ import androidx.core.graphics.BlendModeColorFilterCompat
|
|||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.adapter.CategoryInfoAdapter
|
||||
import code.name.monkey.retromusic.databinding.PreferenceDialogLibraryCategoriesBinding
|
||||
import code.name.monkey.retromusic.extensions.colorButtons
|
||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
||||
import code.name.monkey.retromusic.extensions.materialDialog
|
||||
|
@ -51,15 +51,14 @@ class LibraryPreference @JvmOverloads constructor(
|
|||
class LibraryPreferenceDialog : DialogFragment() {
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val view = layoutInflater
|
||||
.inflate(R.layout.preference_dialog_library_categories, null)
|
||||
val binding = PreferenceDialogLibraryCategoriesBinding.inflate(layoutInflater)
|
||||
|
||||
val categoryAdapter = CategoryInfoAdapter()
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
recyclerView.layoutManager = LinearLayoutManager(activity)
|
||||
recyclerView.adapter = categoryAdapter
|
||||
categoryAdapter.attachToRecyclerView(recyclerView)
|
||||
|
||||
binding.recyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(activity)
|
||||
adapter = categoryAdapter
|
||||
categoryAdapter.attachToRecyclerView(this)
|
||||
}
|
||||
|
||||
return materialDialog(R.string.library_categories)
|
||||
.setNeutralButton(
|
||||
|
@ -68,8 +67,8 @@ class LibraryPreferenceDialog : DialogFragment() {
|
|||
updateCategories(PreferenceUtil.defaultCategories)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton( R.string.done) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.done) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
|
||||
.setView(binding.root)
|
||||
.create()
|
||||
.colorButtons()
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ import android.util.AttributeSet
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
||||
|
@ -32,6 +30,7 @@ import androidx.viewpager.widget.ViewPager
|
|||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.PreferenceNowPlayingScreenItemBinding
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
|
||||
|
@ -116,25 +115,16 @@ private class NowPlayingScreenAdapter(private val context: Context) : PagerAdapt
|
|||
val nowPlayingScreen = values()[position]
|
||||
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val layout = inflater.inflate(
|
||||
R.layout.preference_now_playing_screen_item,
|
||||
collection,
|
||||
false
|
||||
) as ViewGroup
|
||||
collection.addView(layout)
|
||||
|
||||
val image = layout.findViewById<ImageView>(R.id.image)
|
||||
val title = layout.findViewById<TextView>(R.id.title)
|
||||
val proText = layout.findViewById<TextView>(R.id.proText)
|
||||
Glide.with(context).load(nowPlayingScreen.drawableResId).into(image)
|
||||
title.setText(nowPlayingScreen.titleRes)
|
||||
val binding = PreferenceNowPlayingScreenItemBinding.inflate(inflater, collection, true)
|
||||
Glide.with(context).load(nowPlayingScreen.drawableResId).into(binding.image)
|
||||
binding.title.setText(nowPlayingScreen.titleRes)
|
||||
if (isNowPlayingThemes(nowPlayingScreen)) {
|
||||
proText.show()
|
||||
proText.setText(R.string.pro)
|
||||
}else{
|
||||
proText.hide()
|
||||
binding.proText.show()
|
||||
binding.proText.setText(R.string.pro)
|
||||
} else {
|
||||
binding.proText.hide()
|
||||
}
|
||||
return layout
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun destroyItem(
|
||||
|
|
|
@ -69,6 +69,7 @@ interface Repository {
|
|||
suspend fun recentAlbumsHome(): Home
|
||||
suspend fun favoritePlaylistHome(): Home
|
||||
suspend fun suggestionsHome(): Home
|
||||
suspend fun suggestions(): List<Song>
|
||||
suspend fun genresHome(): Home
|
||||
suspend fun playlists(): Home
|
||||
suspend fun homeSections(): List<Home>
|
||||
|
@ -240,21 +241,17 @@ class RealRepository(
|
|||
override suspend fun homeSections(): List<Home> {
|
||||
val homeSections = mutableListOf<Home>()
|
||||
val sections: List<Home> = listOf(
|
||||
suggestionsHome(),
|
||||
topArtistsHome(),
|
||||
topAlbumsHome(),
|
||||
recentArtistsHome(),
|
||||
recentAlbumsHome(),
|
||||
favoritePlaylistHome()
|
||||
// genresHome()
|
||||
)
|
||||
for (section in sections) {
|
||||
if (section.arrayList.isNotEmpty()) {
|
||||
if (section.homeSection != SUGGESTIONS || PreferenceUtil.homeSuggestions) {
|
||||
homeSections.add(section)
|
||||
}
|
||||
}
|
||||
}
|
||||
return homeSections
|
||||
}
|
||||
|
||||
|
@ -374,6 +371,13 @@ class RealRepository(
|
|||
return suggestions
|
||||
}
|
||||
|
||||
override suspend fun suggestions(): List<Song> {
|
||||
if (!PreferenceUtil.homeSuggestions) return listOf<Song>()
|
||||
return NotPlayedPlaylist().songs().shuffled().takeIf {
|
||||
it.size > 9
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
override suspend fun genresHome(): Home {
|
||||
val genres = genreRepository.genres().shuffled()
|
||||
return Home(genres, GENRES, R.string.genres)
|
||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
|
|||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.provider.MediaStore
|
||||
import android.provider.MediaStore.Audio.AudioColumns
|
||||
|
@ -42,11 +43,13 @@ interface SongRepository {
|
|||
|
||||
fun songs(query: String): List<Song>
|
||||
|
||||
fun songsByFilePath(filePath: String): List<Song>
|
||||
fun songsByFilePath(filePath: String, ignoreBlacklist: Boolean = false): List<Song>
|
||||
|
||||
fun song(cursor: Cursor?): Song
|
||||
|
||||
fun song(songId: Long): Song
|
||||
|
||||
fun songsIgnoreBlacklist(uri: Uri): List<Song>
|
||||
}
|
||||
|
||||
class RealSongRepository(private val context: Context) : SongRepository {
|
||||
|
@ -84,15 +87,38 @@ class RealSongRepository(private val context: Context) : SongRepository {
|
|||
return song(makeSongCursor(AudioColumns._ID + "=?", arrayOf(songId.toString())))
|
||||
}
|
||||
|
||||
override fun songsByFilePath(filePath: String): List<Song> {
|
||||
override fun songsByFilePath(filePath: String, ignoreBlacklist: Boolean): List<Song> {
|
||||
return songs(
|
||||
makeSongCursor(
|
||||
AudioColumns.DATA + "=?",
|
||||
arrayOf(filePath)
|
||||
arrayOf(filePath),
|
||||
ignoreBlacklist = ignoreBlacklist
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun songsIgnoreBlacklist(uri: Uri): List<Song> {
|
||||
var filePath = ""
|
||||
context.contentResolver.query(
|
||||
uri,
|
||||
arrayOf(AudioColumns.DATA),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).use { cursor ->
|
||||
if (cursor != null) {
|
||||
if (cursor.count != 0) {
|
||||
cursor.moveToFirst()
|
||||
filePath = cursor.getString(AudioColumns.DATA)
|
||||
println("File Path: $filePath")
|
||||
}
|
||||
}
|
||||
}
|
||||
return songsByFilePath(
|
||||
filePath, true
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSongFromCursorImpl(
|
||||
cursor: Cursor
|
||||
): Song {
|
||||
|
@ -128,13 +154,14 @@ class RealSongRepository(private val context: Context) : SongRepository {
|
|||
|
||||
@JvmOverloads
|
||||
fun makeSongCursor(
|
||||
|
||||
selection: String?,
|
||||
selectionValues: Array<String>?,
|
||||
sortOrder: String = PreferenceUtil.songSortOrder
|
||||
sortOrder: String = PreferenceUtil.songSortOrder,
|
||||
ignoreBlacklist: Boolean = false
|
||||
): Cursor? {
|
||||
var selectionFinal = selection
|
||||
var selectionValuesFinal = selectionValues
|
||||
if (!ignoreBlacklist) {
|
||||
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
|
||||
"$IS_MUSIC AND $selectionFinal"
|
||||
} else {
|
||||
|
@ -161,7 +188,7 @@ class RealSongRepository(private val context: Context) : SongRepository {
|
|||
|
||||
selectionFinal =
|
||||
selectionFinal + " AND " + Media.DURATION + ">= " + (PreferenceUtil.filterLength * 1000)
|
||||
|
||||
}
|
||||
val uri = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||
} else {
|
||||
|
|
|
@ -16,8 +16,10 @@ package code.name.monkey.retromusic.service;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.PlaybackParams;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.net.Uri;
|
||||
import android.os.PowerManager;
|
||||
|
@ -26,14 +28,19 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils;
|
||||
import code.name.monkey.retromusic.ConstantsKt;
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.service.playback.Playback;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
|
||||
/** @author Andrew Neal, Karim Abou Zeid (kabouzeid) */
|
||||
/**
|
||||
* @author Andrew Neal, Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public class MultiPlayer
|
||||
implements Playback, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
|
||||
implements Playback, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
public static final String TAG = MultiPlayer.class.getSimpleName();
|
||||
|
||||
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
|
||||
|
@ -45,10 +52,13 @@ public class MultiPlayer
|
|||
|
||||
private boolean mIsInitialized = false;
|
||||
|
||||
/** Constructor of <code>MultiPlayer</code> */
|
||||
/**
|
||||
* Constructor of <code>MultiPlayer</code>
|
||||
*/
|
||||
MultiPlayer(final Context context) {
|
||||
this.context = context;
|
||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,6 +92,7 @@ public class MultiPlayer
|
|||
} else {
|
||||
player.setDataSource(path);
|
||||
}
|
||||
setPlaybackSpeedPitch(player);
|
||||
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
player.prepare();
|
||||
} catch (Exception e) {
|
||||
|
@ -155,13 +166,17 @@ public class MultiPlayer
|
|||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
/** @return True if the player is ready to go, false otherwise */
|
||||
/**
|
||||
* @return True if the player is ready to go, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return mIsInitialized;
|
||||
}
|
||||
|
||||
/** Starts or resumes playback. */
|
||||
/**
|
||||
* Starts or resumes playback.
|
||||
*/
|
||||
@Override
|
||||
public boolean start() {
|
||||
try {
|
||||
|
@ -172,14 +187,18 @@ public class MultiPlayer
|
|||
}
|
||||
}
|
||||
|
||||
/** Resets the MediaPlayer to its uninitialized state. */
|
||||
/**
|
||||
* Resets the MediaPlayer to its uninitialized state.
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
mCurrentMediaPlayer.reset();
|
||||
mIsInitialized = false;
|
||||
}
|
||||
|
||||
/** Releases resources associated with this MediaPlayer object. */
|
||||
/**
|
||||
* Releases resources associated with this MediaPlayer object.
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
stop();
|
||||
|
@ -187,9 +206,12 @@ public class MultiPlayer
|
|||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
}
|
||||
PreferenceManager.getDefaultSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
/** Pauses playback. Call start() to resume. */
|
||||
/**
|
||||
* Pauses playback. Call start() to resume.
|
||||
*/
|
||||
@Override
|
||||
public boolean pause() {
|
||||
try {
|
||||
|
@ -200,7 +222,9 @@ public class MultiPlayer
|
|||
}
|
||||
}
|
||||
|
||||
/** Checks whether the MultiPlayer is playing. */
|
||||
/**
|
||||
* Checks whether the MultiPlayer is playing.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
return mIsInitialized && mCurrentMediaPlayer.isPlaying();
|
||||
|
@ -291,7 +315,9 @@ public class MultiPlayer
|
|||
return mCurrentMediaPlayer.getAudioSessionId();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
|
||||
mIsInitialized = false;
|
||||
|
@ -308,7 +334,9 @@ public class MultiPlayer
|
|||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCompletion(final MediaPlayer mp) {
|
||||
if (mp.equals(mCurrentMediaPlayer) && mNextMediaPlayer != null) {
|
||||
|
@ -324,5 +352,25 @@ public class MultiPlayer
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setCrossFadeDuration(int duration) { }
|
||||
public void setCrossFadeDuration(int duration) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals(ConstantsKt.PLAYBACK_SPEED) || key.equals(ConstantsKt.PLAYBACK_PITCH)) {
|
||||
setPlaybackSpeedPitch(mCurrentMediaPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlaybackSpeedPitch(MediaPlayer mp) {
|
||||
if (VersionUtils.INSTANCE.hasMarshmallow()) {
|
||||
boolean wasPlaying = mp.isPlaying();
|
||||
mp.setPlaybackParams(new PlaybackParams()
|
||||
.setSpeed(PreferenceUtil.INSTANCE.getPlaybackSpeed())
|
||||
.setPitch(PreferenceUtil.INSTANCE.getPlaybackPitch()));
|
||||
if (!wasPlaying) {
|
||||
if (mp.isPlaying()) mp.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import static code.name.monkey.retromusic.ConstantsKt.BLURRED_ALBUM_ART;
|
|||
import static code.name.monkey.retromusic.ConstantsKt.CLASSIC_NOTIFICATION;
|
||||
import static code.name.monkey.retromusic.ConstantsKt.COLORED_NOTIFICATION;
|
||||
import static code.name.monkey.retromusic.ConstantsKt.CROSS_FADE_DURATION;
|
||||
import static code.name.monkey.retromusic.ConstantsKt.PLAYBACK_SPEED;
|
||||
import static code.name.monkey.retromusic.ConstantsKt.TOGGLE_HEADSET;
|
||||
import static code.name.monkey.retromusic.service.AudioFader.startFadeAnimator;
|
||||
|
||||
|
@ -82,6 +83,7 @@ import code.name.monkey.retromusic.R;
|
|||
import code.name.monkey.retromusic.activities.LockScreenActivity;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetBig;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetCard;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetCircle;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetClassic;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetMD3;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetSmall;
|
||||
|
@ -139,6 +141,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
public static final String META_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".metachanged";
|
||||
public static final String QUEUE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".queuechanged";
|
||||
public static final String PLAY_STATE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".playstatechanged";
|
||||
|
||||
public static final String FAVORITE_STATE_CHANGED =
|
||||
RETRO_MUSIC_PACKAGE_NAME + "favoritestatechanged";
|
||||
public static final String REPEAT_MODE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".repeatmodechanged";
|
||||
|
@ -204,6 +207,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
|
||||
private final AppWidgetMD3 appWidgetMd3 = AppWidgetMD3.Companion.getInstance();
|
||||
|
||||
private final AppWidgetCircle appWidgetCircle = AppWidgetCircle.Companion.getInstance();
|
||||
|
||||
private final BroadcastReceiver widgetIntentReceiver =
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
|
@ -236,6 +241,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
appWidgetMd3.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetCircle.NAME: {
|
||||
appWidgetCircle.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -285,6 +294,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
public void onReceive(final Context context, final Intent intent) {
|
||||
playingNotification.updateFavorite(getCurrentSong(), MusicService.this::startForegroundOrNotify);
|
||||
startForegroundOrNotify();
|
||||
appWidgetCircle.notifyChange(MusicService.this, FAVORITE_STATE_CHANGED);
|
||||
}
|
||||
};
|
||||
private final BroadcastReceiver lockScreenReceiver =
|
||||
|
@ -431,9 +441,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
||||
|
||||
setSessionToken(mediaSession.getSessionToken());
|
||||
if (VersionUtils.INSTANCE.hasMarshmallow()) {
|
||||
notificationManager = getSystemService(NotificationManager.class);
|
||||
}
|
||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
initNotification();
|
||||
|
||||
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
||||
|
@ -939,8 +947,11 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
break;
|
||||
case CLASSIC_NOTIFICATION:
|
||||
updateNotification();
|
||||
playingNotification.setPlaying(isPlaying());
|
||||
playingNotification.updateMetadata(getCurrentSong(), this::startForegroundOrNotify);
|
||||
playingNotification.setPlaying(isPlaying(),this::startForegroundOrNotify);
|
||||
break;
|
||||
case PLAYBACK_SPEED:
|
||||
updateMediaSessionPlaybackState();
|
||||
break;
|
||||
case TOGGLE_HEADSET:
|
||||
registerHeadsetEvents();
|
||||
|
@ -1336,7 +1347,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
.setState(
|
||||
isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||
getSongProgressMillis(),
|
||||
1);
|
||||
PreferenceUtil.INSTANCE.getPlaybackSpeed());
|
||||
|
||||
setCustomAction(stateBuilder);
|
||||
|
||||
|
@ -1426,7 +1437,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
savePositionInTrack();
|
||||
}
|
||||
songPlayCountHelper.notifyPlayStateChanged(isPlaying);
|
||||
playingNotification.setPlaying(isPlaying);
|
||||
playingNotification.setPlaying(isPlaying, this::startForegroundOrNotify);
|
||||
startForegroundOrNotify();
|
||||
break;
|
||||
case FAVORITE_STATE_CHANGED:
|
||||
|
@ -1617,6 +1628,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
appWidgetCard.notifyChange(this, what);
|
||||
appWidgetText.notifyChange(this, what);
|
||||
appWidgetMd3.notifyChange(this, what);
|
||||
appWidgetCircle.notifyChange(this, what);
|
||||
}
|
||||
|
||||
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue